Objects First


switch statements

In order to process each possible value of an object of an enumerated type, we could write a long
if (x==val1) { .. } else if (x==val2) { .. }
else if (x==val3) ...
While such a statement if perfectly OK and if formatted sensibly:
if (x==val1) {
           .. }
else if (x==val2) {
           .. }
else if (x==val3) {
           .. }
else { /* Don't forget to catch unintended errors here! */
      printf("Illegal value for x: %d\n", x);
      }
quite easy to read, C provides us with a short-hand notation in the form of a switch statement.
switch( x ) {
  case val1:
            ....
            break;
  case val2:
            ....
            break;
  case val3:
            ....
            break;
  default:
      printf("Illegal value for x: %d\n", x);
  }
Note carefully the break statements! C switch cases fall through to the next case if the break is not there. This is a particular trap for those used to other languages, such as Pascal, where branches of a case statement do not fall through to the next case. Although a trap for new C programmers, the fall-through property of switch statements may be used in some convenient ways. Consider a system where the user types in single letter commands to the machine - but we don't want to force him or her to ensure that the commands are in upper or lower case, ie if 'A' signifies the 'Add' command, then 'a' should do just as well:
char user_response;
int valid_response;

do {
  user_response = read_user_input("Enter next command");
  valid_response = TRUE;

  switch ( user_response ) {
    case 'a':
    case 'A':
           process_add_command();
           break;
    case 'd':
    case 'D':
           process_delete_command();
           break;
    default:
           printf("%c is not valid, enter A or D\n",
                 user_response );
           valid_response = FALSE;
  }
while( !valid_response );
We can also see that the controlling expression in a switch statement can be a character as well as an enumerated type. In fact, the formal requirement is an integral expression - any expression that evaluates to an integer. Thus enum's and char's can be used because they are promoted to int when used in expressions. Of course, we can use integers directly:
int n = ...;

switch( n ) {
  case 0 : printf("zero"); break;
  case 1 : printf("one"); break;
  case 2 : printf("two"); break;
  default: printf("many");
  }
Note that although this example is acceptable, many switch statements using integer values in the case .. parts would fail the NO MAGIC NUMBERS rule (and earn you a certain failure in the practical programming test!). For example, if a bank's system assigns numeric codes to transactions:
int trans_code = ...;

switch( trans_code ) {
  case 11 : withdraw(); break;
  case 23 : deposit(); break;
  case 13 : balance(); break;
  default: printf("illegal transaction type");
  }
is definitely unacceptable. It should be re-coded as:
/* TransactionType.h - TransactionType class */
typedef enum { withdraw_trans = 11,
               deposit_trans = 23,
               balance_req = 13 } TransactionType;

#include "TransactionType.h"

TransactionType trans_code = ...;
...
switch( trans_code ) {
  case withdraw_trans : withdraw(); break;
  case deposit_trans :  deposit(); break;
  case balance_req :    balance(); break;
  default:              printf("illegal transaction type");
  }
or possibly the equivalent using #define statements to hide the actual transaction type encodings.

Making enum's readable

As an example of the use of switch statements, the problem of making enum variables readable can be solved with a function like this:
char *ColourString( Colour c ) {
  switch( c ) {
    case black : return "black";
    case blue : return "blue";
    case red : return "red";
    case yellow : return "yellow";
    default : return "unknown colour";
    }
}
Note that this function return a char * - or pointer to a character. For more about pointers, refer to later sections of this book. For the moment, note that you can use this function anywhere that you need a string. In particular, you can use it in printf:
Colour c;
c = RectColour( r );
printf("Colour is %s\n", ColourString( c ) );

Key terms

fall-through
a way of specifying a branch of a switch (or equivalent) in other languages which continues on the statements in the following branch. (The alternative style - found in most other languages - branches immediately to the end of the switch statement.)

Continue on to Strings and Pointers
Back to the Table of Contents
© John Morris, 1998