switch Multiple-Selection Statement

We discussed the if single-selection statement and the if...else double-selection statement in Chapter 5. C# provides the switch multiple-selection statement to perform different actions based on the possible values of an expression. Each action is associated with the value of a constant integral expression or a constant string expression that the variable or expression on which the switch is based may assume. A constant integral expression is any expression involving character and integer constants that evaluates to an integer value (i.e., values of type sbyte, byte, short, ushort, int, uint, long, ulong, and char). A constant string expression is any expression composed of string literals that always results in the same string.

GradeBook Class with switch Statement to Count A, B, C, D and F Grades

Figure 6.9 contains an enhanced version of the GradeBook class introduced in Chapter 4 and further developed in Chapter 5. The version of the class we now present not only calculates the average of a set of numeric grades entered by the user, but uses a switch statement to determine whether each grade is the equivalent of an A, B, C, D or F and to increment the appropriate grade counter. The class also displays a summary of the number of students who received each grade. Figure 6.10 shows sample input and output of the GradeBookTest application that uses class GradeBook to process a set of grades.

Figure 6.9. GradeBook class that uses a switch statement to count A, B, C, D and F grades.

1 // Fig. 6.9: GradeBook.cs 2 // GradeBook class uses switch statement to count A, B, C, D and F grades. 3 using System; 4 5 public class GradeBook 6 { 7 private string courseName; // name of course this GradeBook represents 8 private int total; // sum of grades 9 private int gradeCounter; // number of grades entered 10 private int aCount; // count of A grades 11 private int bCount; // count of B grades 12 private int cCount; // count of C grades 13 private int dCount; // count of D grades 14 private int fCount; // count of F grades 15 16 // constructor initializes courseName; 17 // int instance variables are initialized to 0 by default 18 public GradeBook( string name ) 19 { 20 CourseName = name; // initializes courseName 21 } // end constructor 22 23 // property that gets and sets the course name 24 public string CourseName 25 { 26 get 27 { 28 return courseName; 29 } // end get 30 set 31 { 32 courseName = value; 33 } // end set 34 } // end property CourseName 35 36 // display a welcome message to the GradeBook user 37 public void DisplayMessage() 38 { 39 // CourseName gets the name of the course 40 Console.WriteLine( "Welcome to the grade book for {0}! ", 41 CourseName ); 42 } // end method DisplayMessage 43 44 // input arbitrary number of grades from user 45 public void InputGrades() 46 { 47 int grade; // grade entered by user 48 string input; // text entered by the user 49 50 Console.WriteLine( "{0} {1}", 51 "Enter the integer grades in the range 0-100.", 52 "Type z and press Enter to terminate input:" ); 53 54 input = Console.ReadLine(); // read user input 55 56 // loop until user enters the end-of-file indicator ( z) 57 while ( input != null ) 58 { 59 grade = Convert.ToInt32( input ); // read grade off user input 60 total += grade; // add grade to total 61 gradeCounter++; // increment number of grades 62 63 // call method to increment appropriate counter 64 IncrementLetterGradeCounter( grade ); 65 66 input = Console.ReadLine(); // read user input 67 } // end while 68 } // end method InputGrades 69 70 // add 1 to appropriate counter for specified grade 71 private void IncrementLetterGradeCounter( int grade ) 72 { 73 // determine which grade was entered 74 switch ( grade / 10 ) 75 { 76 case 9: // grade was in the 90s 77 case 10: // grade was 100 78 aCount++; // increment aCount 79 break; // necessary to exit switch 80 case 8: // grade was between 80 and 89 81 bCount++; // increment bCount 82 break; // exit switch 83 case 7: // grade was between 70 and 79 84 cCount++; // increment cCount 85 break; // exit switch 86 case 6: // grade was between 60 and 69 87 dCount++; // increment dCount 88 break; // exit switch 89 default: // grade was less than 60 90 fCount++; // increment fCount 91 break; // exit switch 92 } // end switch 93 } // end method IncrementLetterGradeCounter 94 95 // display a report based on the grades entered by the user 96 public void DisplayGradeReport() 97 { 98 Console.WriteLine( " Grade Report:" ); 99 100 // if user entered at least one grade... 101 if ( gradeCounter != 0 ) 102 { 103 // calculate average of all grades entered 104 double average = ( double ) total / gradeCounter; 105 106 // output summary of results 107 Console.WriteLine( "Total of the {0} grades entered is {1}", 108 gradeCounter, total ); 109 Console.WriteLine( "Class average is {0:F2}", average ); 110 Console.WriteLine( "{0}A: {1} B: {2} C: {3} D: {4} F: {5}", 111 "Number of students who received each grade: ", 112 aCount, // display number of A grades 113 bCount, // display number of B grades 114 cCount, // display number of C grades 115 dCount, // display number of D grades 116 fCount ); // display number of F grades 117 } // end if 118 else // no grades were entered, so output appropriate message 119 Console.WriteLine( "No grades were entered" ); 120 } // end method DisplayGradeReport 121 } // end class GradeBook

Figure 6.10. Create GradeBook object, input grades and display grade report.

(This item is displayed on page 242 in the print version)

1 // Fig. 6.10: GradeBookTest.cs 2 // Create GradeBook object, input grades and display grade report. 3 4 public class GradeBookTest 5 { 6 public static void Main( string[] args ) 7 { 8 // create GradeBook object myGradeBook and 9 // pass course name to constructor 10 GradeBook myGradeBook = new GradeBook( 11 "CS101 Introduction to C# Programming" ); 12 13 myGradeBook.DisplayMessage(); // display welcome message 14 myGradeBook.InputGrades(); // read grades from user 15 myGradeBook.DisplayGradeReport(); // display report based on grades 16 } // end Main 17 } // end class GradeBookTest  

Welcome to the grade book for CS101 Introduction to C# Programming! Enter the integer grades in the range 0-100. Type z and press Enter to terminate input: 99 92 45 100 57 63 76 14 92 ^Z Grade Report: Total of the 9 grades entered is 638 Class average is 70.89 Number of students who received each grade: A: 4 B: 0 C: 1 D: 1 F: 3

Like earlier versions of the class, class GradeBook (Fig. 6.9) declares instance variable courseName (line 7), property CourseName (lines 2434) to access courseName and method DisplayMessage (lines 3742) to display a welcome message to the user. The class also contains a constructor (lines 1821) that initializes the course name.

Class GradeBook also declares instance variables total (line 8) and gradeCounter (line 9), which keep track of the sum of the grades entered by the user and the number of grades entered, respectively. Lines 1014 declare counter variables for each grade category. Class GradeBook maintains total, gradeCounter and the five letter-grade counters as instance variables so that these variables can be used or modified in any of the class's methods. Note that the class's constructor (lines 1821) sets only the course namethe remaining seven instance variables are ints and are initialized to 0 by default.

Class GradeBook contains three additional methodsInputGrades, IncrementLetterGradeCounter and DisplayGradeReport. Method InputGrades (lines 4568) reads an arbitrary number of integer grades from the user using sentinel-controlled repetition and updates instance variables total and gradeCounter. Method InputGrades calls method IncrementLetterGradeCounter (lines 7193) to update the appropriate letter-grade counter for each grade entered. Class GradeBook also contains method DisplayGradeReport (lines 96120), which outputs a report containing the total of all grades entered, the average of the grades and the number of students who received each letter grade. Let's examine these methods in more detail.

Lines 4748 in method InputGrades declare variables grade and input, which will store the user's input first as a string (in the variable input) then convert it to an int to store in the variable grade. Lines 5052 prompt the user to enter integer grades and to type z then press Enter to terminate the input. The notation z means to simultaneously press both the Ctrl key and the z key when typing in a Command Prompt. z is the Windows key sequence for typing the end-of-file indicator. This is one way to inform an application that there is no more data to input. (The end-of-file indicator is a system-dependent keystroke combination. On many non-Windows systems, end-of-file is entered by typing d.) In Chapter 18, Files and Streams, we will see how the end-of-file indicator is used when an application reads its input from a file. [Note: Windows typically displays the characters ^Z in a Command Prompt when the end-of-file indicator is typed, as shown in the output of Fig. 6.10.]

Line 54 uses the ReadLine method to get the first line that the user entered and store it in variable input. The while statement (lines 5767) processes this user input. The condition at line 57 checks if the value of input is a null reference. The Console class's ReadLine method will only return null if the user typed an end-of-file indicator. As long as the end-of-file indicator has not been typed, input will not contain a null reference, and the condition will pass.

Line 59 converts the string in input to an int type. Line 60 adds grade to total. Line 61 increments gradeCounter. The class's DisplayGradeReport method uses these variables to compute the average of the grades. Line 64 calls the class's IncrementLetterGradeCounter method (declared in lines 7193) to increment the appropriate letter-grade counter, based on the numeric grade entered.

Method IncrementLetterGradeCounter contains a switch statement (lines 7492) that determines which counter to increment. In this example, we assume that the user enters a valid grade in the range 0100. A grade in the range 90100 represents A, 8089 represents B, 7079 represents C, 6069 represents D and 059 represents F. The switch statement consists of a block that contains a sequence of case labels and an optional default label. These are used in this example to determine which counter to increment based on the grade.

When the flow of control reaches the switch, the application evaluates the expression in the parentheses (grade / 10) following keyword switch. This is called the switch expression. The application compares the value of the switch expression with each case label. The switch expression in line 74 performs integer division, which truncates the fractional part of the result. Thus, when we divide any value in the range 0100 by 10, the result is always a value from 0 to 10. We use several of these values in our case labels. For example, if the user enters the integer 85, the switch expression evaluates to int value 8. The switch compares 8 with each case. If a match occurs (case 8: at line 80), the application executes the statements for that case. For the integer 8, line 81 increments bCount, because a grade in the 80s is a B. The break statement (line 82) causes program control to proceed with the first statement after the switchin this application, we reach the end of method IncrementLetterGradeCounter's body, so control returns to line 66 in method InputGrades (the first line after the call to IncrementLetterGradeCounter). This line uses the ReadLine method to read the next line entered by the user and assign it to the variable input. Line 67 marks the end of the body of the while loop that inputs grades (lines 5767), so control flows to the while's condition (line 57) to determine whether the loop should continue executing based on the value just assigned to the variable input.

The cases in our switch explicitly test for the values 10, 9, 8, 7 and 6. Note the case labels at lines 7677 that test for the values 9 and 10 (both of which represent the grade A). Listing case labels consecutively in this manner with no statements between them enables the cases to perform the same set of statementswhen the switch expression evaluates to 9 or 10, the statements in lines 7879 execute. The switch statement does not provide a mechanism for testing ranges of values, so every value to be tested must be listed in a separate case label. Note that each case can have multiple statements. The switch statement differs from other control statements in that it does not require braces around multiple statements in each case.

In C, C++, and many other programming languages that use the switch statement, the break statement is not required at the end of a case. Without break statements, each time a match occurs in the switch, the statements for that case and subsequent cases execute until a break statement or the end of the switch is encountered. This is often referred to as "falling through" to the statements in subsequent cases. This frequently leads to logic errors when you forget the break statement. For this reason, C# has a "no fall through" rule for cases in a switchafter the statements in a case execute, you are required to include a statement that terminates the case, such as a break, a return, or a throw. (We discuss the tHRow statement in Chapter 12.)

Common Programming Error 6 7

Forgetting a break statement when one is needed in a switch is a syntax error.

If no match occurs between the switch expression's value and a case label, the statements after the default label (lines 9091) execute. We use the default label in this example to process all switch-expression values that are less than 6that is, all failing grades. If no match occurs and the switch does not contain a default label, program control simply continues with the first statement after the switch statement.

GradeBookTest Class That Demonstrates Class GradeBook

Class GradeBookTest (Fig. 6.10) creates a GradeBook object (lines 1011). Line 13 invokes the object's DisplayMessage method to output a welcome message to the user. Line 14 invokes the object's InputGrades method to read a set of grades from the user and keep track of the sum of all the grades entered and the number of grades. Recall that method InputGrades also calls method IncrementLetterGradeCounter to keep track of the number of students who received each letter grade. Line 15 invokes method DisplayGradeReport of class GradeBook, which outputs a report based on the grades entered. Line 101 of class GradeBook (Fig. 6.9) determines whether the user entered at least one gradethis avoids dividing by zero. If so, line 104 calculates the average of the grades. Lines 107116 then output the total of all the grades, the class average and the number of students who received each letter grade. If no grades were entered, line 119 outputs an appropriate message. The output in Fig. 6.10 shows a sample grade report based on 9 grades.

Note that class GradeBookTest (Fig. 6.10) does not directly call GradeBook method IncrementLetterGradeCounter (lines 7193 of Fig. 6.9). This method is used exclusively by method InputGrades of class GradeBook to update the appropriate letter-grade counter as each new grade is entered by the user. Method IncrementLetterGradeCounter exists solely to support the operations of class GradeBook's other methods and thus is declared private. Recall from Chapter 4 that methods declared with access modifier private can be called only by other methods of the class in which the private methods are declared. Such methods are commonly referred to as utility methods or helper methods, because they can be called only by other methods of that class and are used to support the operation of those methods.

switch Statement UML Activity Diagram

Figure 6.11 shows the UML activity diagram for the general switch statement. Every set of statements after a case label must end its execution in a break or return statement to terminate the switch statement after processing the case. Typically, you will use break statements. Figure 6.11 emphasizes this by including break statements in the activity diagram. The diagram makes it clear that the break statement at the end of a case causes control to exit the switch statement immediately.

Figure 6.11. switch multiple-selection statement UML activity diagram with break statements.

(This item is displayed on page 244 in the print version)

Software Engineering Observation 6 2

Provide a default label in switch statements. Cases not explicitly tested in a switch that lacks a default label are ignored. Including a default label focuses you on the need to process exceptional conditions.

Good Programming Practice 6 7

Although each case and the default label in a switch can occur in any order, place the default label last for clarity.

When using the switch statement, remember that the expression after each case can be only a constant integral expression or a constant string expressionthat is, any combination of constants that evaluates to a constant value of an integral or string type. An integer constant is simply an integer value (e.g., 7, 0 or 221). In addition, you can use character constantsspecific characters in single quotes, such as 'A', '7' or '$'which represent the integer values of characters. (Appendix D, ASCII Character Set, shows the integer values of the characters in the ASCII character set, which is a subset of the Unicode character set used by C#.) A string constant is a sequence of characters in double quotes, such as "Welcome to C# Programming!".

The expression in each case also can be a constanta variable that contains a value which does not change for the entire application. Such a variable is declared with the keyword const (discussed in Chapter 7, Methods: A Deeper Look). C# also has a feature called enumerations, which we also present in Chapter 7. Enumeration constants can also be used in case labels. In Chapter 11, Polymorphism, Interfaces & Operator Overloading, we present a more elegant way to implement switch logicwe use a technique called polymorphism to create applications that are often clearer, easier to maintain and easier to extend than applications using switch logic.

Категории