8.2 switch Statement

I l @ ve RuBoard

The switch statement is similar to a chain of if-else statements. The general form of a switch statement is:

 switch (   expression   ) {      case   constant1   :   statement   . . . .          break;      case   constant2   :   statement   . . . .          // Fall through     default:   statement   . . . .          break;      case   constant3   :   statement   . . . .          break;  } 

The switch statement evaluates the value of an expression and branches to one of the case statements. Duplicate statements are not allowed, so only one case will be selected. The expression must evaluate to an integer, character, or enumeration.

The case statements can be in any order and must be constants. The default statement can be put anywhere in the switch .

When C++ sees a switch statement, it evaluates the expression and then looks for a matching case statement. If none is found, the default statement is used. If no default is found, the statement does nothing.

A break statement inside a switch tells the computer to continue the execution after the switch . If the break is not there, execution continues with the next statement.

The switch statement is very similar to the PASCAL case statement. The main differences are that while PASCAL allows only one statement after the label, C++ allows many. C++ keeps executing until it hits a break statement or the end of the switch . In PASCAL you can't "fall through" from one case to another. In C++ you can.

The calculator program in Chapter 7 contains a series of if-else statements.

 if (operator == '+') {              result += value;          } else if (operator == '-') {              result -= value;          } else if (operator == '*') {              result *= value;          } else if (operator == '/') {              if (value == 0) {                  std::cout << "Error: Divide by zero\n";                  std::cout << "   operation ignored\n";              } else                  result /= value;          } else {              std::cout << "Unknown operator " << operator << '\n';         } 

This section of code can easily be rewritten as a switch statement. In this switch , we use a different case for each operation. The default clause takes care of all the illegal operators.

Rewriting the program using a switch statement makes it not only simpler, but also easier to read, as seen in Example 8-5.

Example 8-5. calc-sw/calc3.cpp
 #include <iostream> int   result;      // the result of the calculations  char  oper_char;   // operator the user specified  int   value;       // value specified after the operator  int main(  ) {     result = 0;                 // initialize the result      // loop forever (or until break reached)     while (true) {         std::cout << "Result: " << result << '\n';         std::cout << "Enter operator and number: ";         std::cin >> oper_char >> value;         if ((oper_char == 'q')  (oper_char == 'Q'))             break;         switch (oper_char) {             case '+':                 result += value;                 break;             case '-':                 result -= value;                 break;             case '*':                 result *= value;                 break;             case '/':                 if (value == 0) {                     std::cout << "Error:Divide by zero\n";                     std::cout << "   operation ignored\n";                 } else                     result /= value;                 break;             default:                 std::cout << "Unknown operator " << oper_char << '\n';                 break;         }     }     return (0); } 

A break statement is not required at the end of a case . If the break is not there, execution will continue with the next statement.

For example:

 control = 0;  // A not so good example of programming  switch (control) {          case 0:                  std::cout << "Reset\n";          case 1:                  std::cout << "Initializing\n";                  break;          case 2:                  std::cout "Working\n";  } 

In this case, when control == 0 , the program prints:

 Reset  Initializing 

Case 0 does not end with a break statement. After printing "Reset" the program falls through to the next statement (case 1) and prints "Initializing".

But there is a problem with this syntax. You can't be sure that the program is supposed to fall through from case 0 to case 1, or if the programmer forgot to put in a break statement. To clear up this confusion, a case section should always end with a break statement or the comment // fall through .

 // A better example of programming switch (control) {          case 0:                  std::cout << "Reset\n";                  // Fall through         case 1:                  std::cout << "Initializing\n";                  break;          case 2:                  std::cout << "Working\n";  } 

Because case 2 is last, it doesn't absolutely need a break statement. A break would cause the program to skip to the end of the switch , but we're already there.

But suppose we modify the program slightly and add another case to the switch :

 // We have a little problem switch (control) {          case 0:                  std::cout << "Reset\n";                  // Fall through          case 1:                  std::cout << "Initializing\n";                  break;          case 2:                  std::cout << "Working\n";          case 3:                  std::cout << "Closing down\n";  } 

Now when control == 2 the program prints:

 Working  Closing down 

This is an unpleasant surprise. The problem is caused by the fact that case 2 is no longer the last case . We fall through. (Unintentionally, or otherwise we would have included a // Fall through comment.) A break is now necessary. If you always put in a break statement, you don't have to worry about whether or not it is really needed.

 // Almost there switch (control) {          case 0:                  std::cout << "Reset\n";                  // Fall through         case 1:                  std::cout << "Initializing\n";                  break;          case 2:                  std::cout << "Working\n";                  break;  } 

Finally, we ask the question: What happens when control == 5 ? In this case, since there is no matching case or a default clause, the entire switch statement is skipped .

In this example, the programmer did not include a default statement because control will never be anything but 0, 1, or 2. However, variables can get assigned strange values, so we need a little more defensive programming.

 // The final version switch (control) {      case 0:          std::cout << "Reset\n";          // Fall through     case 1:          std::cout << "Initializing\n";          break;      case 2:          std::cout << "Working\n";          break;      default:          assert("Internal error: Impossible control value" != 0);         break;  } 

In this case we've put in a default that triggers an assert failure. The test in this case is a C-style string ("Internal error....") and a comparison ( != 0 ). Because of the way C++ stores strings, this test will always fail, which in turn will cause the assert to abort the program.

Although a default is not required, it should be put in every switch . Even though the default may be just:

 default:          // Do nothing         break; 

it should be included. This indicates that you want to ignore out-of-range data.

I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

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