Multibranch if-else Statements

   


Multibranch if-else Statements

Notice how the value of balance in Listing 8.2 determines which of the five different print statements the program will execute. Letting the value of a variable determine which statement (or compound statement) to execute of several possible alternatives is so commonplace in the programming world that a standardized system has been devised for writing the nested if-else structures used to implement this functionality. The resulting structures are called multibranch if-else statements.

Let's have a look at how we can turn Listing 8.2 into this standard style. We start by changing the flowchart of Figure 8.10 to form a new flowchart that yields the same results but follows a couple of standard conventions:

  • Only the false arrow flowing away from a decision symbol can flow to another decision symbol.

  • Every true arrow flowing away from a decision symbol flows to an action symbol and from the action symbol to the next statement in the program.

By inspecting Figure 8.10, we realize that the first and third decision symbols do not comply with the stated conventions because the true arrow leads to another decision symbol. Consequently, we need to call the true arrow false and the false arrow true, but without altering the logic. This can be accomplished by exchanging the greater-than-or-equal-to symbol (>=) with the smaller-than (<) symbol, as shown in Figure 8.11. We have likewise flip-flopped the false/true arrows of the third decision symbol while simultaneously exchanging the => symbol with the < symbol. The final complying flowchart is displayed in Figure 8.11.

Figure 8.11. The logic behind a multibranch if-else statement.
graphics/08fig11.gif

We are now ready to implement the logic expressed with the flowchart of Figure 8.11. By using nested if-else statements and adhering to the style of indentation used up to now, we end up with the source code displayed in Listing 8.3, which represents exactly the same functionality (and therefore generates the same output) as the program of Listing 8.2.

Listing 8.3 PreMultibranch.cs
01: using System; 02: 03: class PreMultibranch 04: { 05:     public static void Main() 06:     { 07:         decimal balance; 08: 09:         Console.Write("Enter balance: "); 10:         balance = Convert.ToDecimal(Console.ReadLine()); 11:         if(balance < 5000) 12:             Console.WriteLine("balance < 5000. Category C"); 13:         else 14:             if(balance <= 20000) 15:                 Console.WriteLine("5000 <= balance <= 20000. Category A"); 16:             else 17:                 if(balance < 60000) 18:                     Console.WriteLine("20000 < balance < 60000. Category C"); 19:                 else 20:                     if(balance <= 75000) 21:                         Console.WriteLine("60000 <= balance <= 75000 "); 22:                     else 23:                         Console.WriteLine("Balance is in category C"); 24:     } 25: } 

The output from Listing 8.3 is identical to that of Listing 8.2.

The program evaluates the Boolean expressions found in lines 11, 14, 17, and 20 in a sequential manner, starting with line 11. As long as the Boolean expressions are false, execution moves to the next indented if-else statement. When a Boolean expression is found to be true, the statement immediately after is executed. When that happens, we know that all previous Boolean expressions except the last one are false. This allows us to make certain deductions about the state of the program in this case, about the value of balance. For example, if one sample run of the program results in the statement of line 21 being executed, we know that (balance < 60000) of line 17 is false and that (balance <= 75000) of line 20 is true. In turn, this allows us to deduce that (60000 balance 75000).

Programmers have devised a standard indentation style when writing multibranch if-else statements that reflects their purpose and the way they think about these structures. To fully comply with this style, we need to change the indenting of Listing 8.3 to that shown in Listing 8.4, which still represents exactly the same functionality.

Listing 8.4 MultibranchBalanceAssessment.cs
01: using System; 02: 03: class MultibranchBalanceAssessment 04: { 05:     public static void Main() 06:     { 07:         decimal balance; 08: 09:         Console.Write("Enter balance: "); 10:         balance = Convert.ToDecimal(Console.ReadLine()); 11:         if(balance < 5000) 12:             Console.WriteLine("balance < 5000. Category C"); 13:         else if(balance <= 20000) 14:             Console.WriteLine("5000 <= balance <= 20000. Category A"); 15:         else if(balance < 60000) 16:             Console.WriteLine("20000 < balance < 60000. Category C"); 17:         else if(balance <= 75000) 18:             Console.WriteLine("60000 <= balance <= 75000. Category B"); 19:         else 20:             Console.WriteLine("balance > 75000. Category C"); 21:     } 22: } 

The output from Listing 8.4 is identical to that of Listing 8.3.

Listing 8.4 represents exactly the same program as Listing 8.3, but it conforms to the indenting style associated with multibranch if-else statements. Each nested if(<Boolean_expression>) has simply been moved up one line and positioned next to the previous else keyword. The step wise indenting seen in Listing 8.3 is replaced with statements following a vertical line. Because multibranch if-else statements can be extended to contain any number of if-else statements, the indenting style in Listing 8.4 will not, as the style of Listing 8.3, cause you to eventually indent yourself out of the screen (or paper).

Syntax Box 8.5 The Multibranch if-else Statement

 Multibranch_if-else_Statement::= if (<Boolean_expression_1>)      <Statement_1>; | <Compound_statement_1> else if (<Boolean_expression_2>)      <Statement_2>; | <Compound_statement_2>                ...... else if (<Boolean_expression_n>)      <Statement_n>; | <Compound_statement_n> else      <Default_statement>; | <Default_compound_statement> 

Note: The <Default_statement>; | <Default_compound_statement> part is only executed if all previous Boolean expressions are false.

Only Use the default_statement for Genuine Defaults in Multibranch if-else Statements

Line 20 of Listing 8.4 contains what Syntax Box 8.5 denotes a <Default_statement>. Whenever this line is executed, we can with confidence say that balance is greater than 75000 because all other options have been effectively eliminated. This matches perfectly well with the message printed by line 20.

Listing 8.5 presents an example of the incorrect use of the default option. It asks the user to enter one of the three letters (A, B, or C) and responds by simply telling the user which letter was entered.

Listing 8.5 ChooseAction.cs
01: using System; 02: 03: class ChooseAction 04: { 05:     public static void Main() 06:     { 07:         string choice; 08: 09:         Console.Write("Enter either A, B or C: "); 10:         choice = Console.ReadLine(); 11:         if(choice == "A") 12:             Console.WriteLine("You entered an A"); 13:         else if (choice == "B") 14:             Console.WriteLine("You entered a B"); 15:         else 16:             Console.WriteLine("You entered a C");      //unsound 17:     } 18: } 

Sample output 1:

 Enter either A, B or C: B<enter> You entered a B 

Sample output 2:

 Enter either A, B or C: F<enter> You entered a C.  

Line 16 is a default statement and mistakenly expects the letter entered by the user to always be a C if it is not an A and not a B. The sample output exposes the problem. As long as the user enters one of the letters (A, B, or C), there is no problem. However, any other letter, such as F, is incorrectly defaulted through else in line 15 to be a C.

Let's improve the code in Listing 8.5. First, we need to make sure that the message in line 16 corresponds with all previous Boolean expressions of the multibranch if-else statement. This can be achieved by explicitly testing for the letter C in line 15. Consequently, we change line 15 to

 15:         else if (choice == "C") 

The <Default_statement> is now unused, so we can put it to good use by letting it detect incorrect user input, as shown in lines 17 and 18 of Listing 8.6. If the flow of execution reaches line 18, we can be confident that the letter entered is not an A, B, or C. Otherwise, it would have been detected by any of the three Boolean expressions in lines 11, 13, and 15.

Listing 8.6 Incomplete Code Snippet
15:         else if (choice == "C") 16:             Console.WriteLine("You entered a C"); 17:         else 18:              Console.WriteLine("Invalid input. Letter was not A, B or C"); 19:     } 20: } 

Tip

graphics/bulb.gif

This leads us to a second general recommendation when constructing multibranch if-else statements detect errors with the <Default_statement> if it is unused.


Tip

graphics/bulb.gif

Avoid too deeply nested if-else statements. In many cases, programmers cannot understand more than three to four levels of nested if-else statements.

Deep nesting can be prevented by

  • Redesigning the Boolean expression. This process can often be facilitated through the use of logical operators, as shown in the forthcoming section.

  • Breaking the code into simpler methods.



   


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net