C++

Switch Statements

In previous unit, you saw how to write if and if/else statements. These can become quite confusing when nested too deeply, and C++ offers an alternative. Unlike if, which evaluates one value, switch statements allow you to branch on any of a number of different values. The general form of the switch statement is:

switch (expression)

{

case valueOne: statement;

break;

case valueTwo: statement;

break;

....

case valueN: statement;

break;

default: statement;

}

expression is any legal C++ expression, and the statements are any legal C++ statements or block of statements. switch evaluates expression and compares the result to each of the case values. Note, however, that the evaluation is only for equality; relational operators may not be used here, nor can Boolean operations.

If one of the case values matches the expression, execution jumps to those statements and continues to the end of the switch block, unless a break statement is encountered. If nothing matches, execution branches to the optional default statement. If there is no default and there is no matching value, execution falls through the switch statement and the statement ends.

NOTE: It is almost always a good idea to have a default case in switch statements. If you have no other need for the default, use it to test for the supposedly impossible case, and print out an error message; this can be a tremendous aid in debugging.

It is important to note that if there is no break statement at the end of a case statement, execution will fall through to the next case statement. This is sometimes necessary, but usually is an error. If you decide to let execution fall through, be sure to put a comment, indicating that you didn’t just forget the break.

Listing 7.16 illustrates use of the switch statement.

Listing 7.16. Demonstrating the switch statement.

1: //Listing 7.16

2: // Demonstrates switch statement

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: unsigned short int number;

9: cout << "Enter a number between 1 and 5: ";

10: cin >> number;

11: switch (number)

12: {

13: case 0: cout << "Too small, sorry!";

14: break;

15: case 5: cout << "Good job!\n"; // fall through

16: case 4: cout << "Nice Pick!\n"; // fall through

17: case 3: cout << "Excellent!\n"; // fall through

18: case 2: cout << "Masterful!\n"; // fall through

19: case 1: cout << "Incredible!\n";

20: break;

21: default: cout << "Too large!\n";

22: break;

23: }

24: cout << "\n\n";

25: return 0;

26: }

Output: 

Enter a number between 1 and 5: 3

Excellent!

Masterful!

Incredible!

Enter a number between 1 and 5: 8

Too large!

Analysis: The user is prompted for a number. That number is given to the switch statement. If the number is 0, the case statement on line 13 matches, the message Too small, sorry! is printed, and the break statement ends the switch. If the value is 5, execution switches to line 15 where a message is printed, and then falls through to line 16, another message is printed, and so forth until hitting the break on line 20. The net effect of these statements is that for a number between 1 and 5, that many messages are printed. If the value of number is not 0-5, it is assumed to be too large, and the default statement is invoked on line 21.

The switch Statement

The syntax for the switch statement is as follows:

switch (expression)

{

case valueOne: statement;

case valueTwo: statement;

....

case valueN: statement

default: statement;

}

The switch statement allows for branching on multiple values of expression. The expression is evaluated, and if it matches any of the case values, execution jumps to that line. Execution continues until either the end of the switch statement or a break statement is encountered. If expression does not match any of the case statements, and if there is a default statement, execution switches to the default statement, otherwise the switch statement ends.

Example 1

switch (choice)

{

case 0:

cout << "Zero!" << endl;

break

case 1:

cout << "One!" << endl;

break;

case 2:

cout << "Two!" << endl;

default:

cout << "Default!" << endl;

}

Example 2

switch (choice)

{

choice 0:

choice 1:

choice 2:

cout << "Less than 3!";

break;

choice 3:

cout << "Equals 3!";

break;

default:

cout << "greater than 3!";

}

Using a switch Statement with a Menu

Listing 7.17 returns to the for(;;) loop discussed earlier. These loops are also called forever loops, as they will loop forever if a break is not encountered. The forever loop is used to put up a menu, solicit a choice from the user, act on the choice, and then return to the menu. This will continue until the user chooses to exit.

NOTE: Some programmers like to write

#define EVER ;;

for (EVER)

{

// statements...

}

New Term: A forever loop is a loop that does not have an exit condition. In order to exit the loop, a break statement must be used. Forever loops are also known as eternal loops.

Listing 7.17. Demonstrating a forever loop.

1: //Listing 7.17

2: //Using a forever loop to manage

3: //user interaction

4: #include <iostream.h>

5:

6: // types & defines

7: enum BOOL { FALSE, TRUE };

8: typedef unsigned short int USHORT;

9:

10: // prototypes

11: USHORT menu();

12: void DoTaskOne();

13: void DoTaskMany(USHORT);

14:

15: int main()

16: {

17:

18: BOOL exit = FALSE;

19: for (;;)

20: {

21: USHORT choice = menu();

22: switch(choice)

23: {

24: case (1):

25: DoTaskOne();

26: break;

27: case (2):

28: DoTaskMany(2);

29: break;

30: case (3):

31: DoTaskMany(3);

32: break;

33: case (4):

34: continue; // redundant!

35: break;

36: case (5):

37: exit=TRUE;

38: break;

39: default:

40: cout << "Please select again!\n";

41: break;

42: } // end switch

43:

44: if (exit)

45: break;

46: } // end forever

47: return 0;

48: } // end main()

49:

50: USHORT menu()

51: {

52: USHORT choice;

53:

54: cout << " **** Menu ****\n\n";

55: cout << "(1) Choice one.\n";

56: cout << "(2) Choice two.\n";

57: cout << "(3) Choice three.\n";

58: cout << "(4) Redisplay menu.\n";

59: cout << "(5) Quit.\n\n";

60: cout << ": ";

61: cin >> choice;

62: return choice;

63: }

64:

65: void DoTaskOne()

66: {

67: cout << "Task One!\n";

68: }

69:

70: void DoTaskMany(USHORT which)

71: {

72: if (which == 2)

73: cout << "Task Two!\n";

74: else

75: cout << "Task Three!\n";

76: }

Output: 

**** Menu ****

(1) Choice one.

(2) Choice two.

(3) Choice three.

(4) Redisplay menu.

(5) Quit.

: 1

Task One!

**** Menu ****

(1) Choice one.

(2) Choice two.

(3) Choice three.

(4) Redisplay menu.

(5) Quit.

: 3

Task Three!

**** Menu ****

(1) Choice one.

(2) Choice two.

(3) Choice three.

(4) Redisplay menu.

(5) Quit.

: 5

Analysis: This program brings together a number of concepts from this unit and previous unit. It also shows a common use of the switch statement. On line 7, an enumeration, BOOL, is created, with two possible values: FALSE, which equals 0, as it should, and TRUE, which equals 1. On line 8, typedef is used to create an alias, USHORT, for unsigned short int.
The forever loop begins on 19. The menu() function is called, which prints the menu to the screen and returns the user’s selection. The switch statement, which begins on line 22 and ends on line 42, switches on the user’s choice.

If the user enters 1, execution jumps to the case 1: statement on line 24. Line 25 switches execution to the DoTaskOne() function, which prints a message and returns. On its return, execution resumes on line 26, where the break ends the switch statement, and execution falls through to line 43. On line 44, the variable exit is evaluated. If it evaluates true, the break on line 45 will be executed and the for(;;) loop will end, but if it evaluates false, execution resumes at the top of the loop on line 19.

Note that the continue statement on line 34 is redundant. If it were left out and the break statement were encountered, the switch would end, exit would evaluate FALSE, the loop would reiterate, and the menu would be reprinted. The continue does, however, bypass the test of exit.

DO use switch statements to avoid deeply nested if statements. DON’T forget break at the end of each case unless you wish to fall through. DO carefully document all intentional fall-through cases. DO put a default case in switch statements, if only to detect seemingly impossible situations.

Back to Index