Switch, Select-Case

If we need to compare a single expression to a number of different constant values, we can do a series of else-ifs as we did above to check multiple age ranges. A cleaner, more readable, and probably faster option is the C switch statement or the Fortran select case statement. The expression being compared, such as the variable age in the if examples above, is called the selector.

In standard C, we can only have one value per case. Cases can be placed back-to-back in free format, however, which is usually good enough.

    switch(age)
    {
        case 0: case 1: case 2:
            puts("No peanuts for you! You might choke on them.");
            break;
        case 3: case 4: case 5: case 6: case 7: case 8: case 9:
            puts("Ask your mom if you can have some peanuts.");
            break;
        case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17:
            puts("You get free peanuts!");
            --peanut_inventory - 1;
            break;
        default:
            puts("No free peanuts for you!");
    }
        

The GCC and Clang/LLVM compilers have an extension to support ranges. Note that this is not portable. Using else if may be a better strategy where large ranges of values are needed for each case.

    switch(age)
    {
        case 0 ... 2:
            puts("No peanuts for you! You might choke on them.");
            break;
        case 3 ... 9:
            puts("Ask your mom if you can have some peanuts.");
            break;
        case 10 ... 17:
            puts("You get free peanuts!");
            --peanut_inventory - 1;
            break;
        default:
            puts("No free peanuts for you!");
    }
        

The standard Fortran select case supports ranges:

    select case (age)
        case (0:2)
            print *, 'No peanuts for you! You might choke on them.'
        case (3:9)
            print *, 'Ask your mom if you can have some peanuts.'
        case (10:17)
            print *, 'You get free peanuts!'
            peanut_inventory = peanut_inventory - 1
        case default
            print *, 'No free peanuts for you!'
    end case
        

In the Fortran select case statement, control jumps to the end case automatically after executing the chosen case.

In the C switch statement, this is not true. The switch statement causes a jump to the correct case, but execution will continue into the cases that follow until a break statement is encountered. This feature is occasionally useful where the statements that should be executed for case 'B' are a subset of those for case 'A'. In this situation, we simply place case 'B' after case 'A' and omit the break after case 'A'.

switch(food)
{
    case    CHEESE:
        puts("This selection is high in fat.");
        // Continue into case B below, since cheese is high
        // in calories as well.
    case    POTATOES:
    case    PRETZELS:
        puts("This selection is high in calories.");
        break;
}
        

The selector value must be an integral type, i.e. integer, logical, or character. Real numbers are a continuous type, and floating point's limited precision makes comparison for equality uncertain since the selector value likely contains some round-off error. Since switch and select case constructs compare for equality and we should never check for equality with floating point types, it is not feasible to use floating point here.

A switch or select-case statement is sometimes more efficient than the equivalent if-then-elseif...endif series. The if-then-elseif...endif has to check every value until it finds the one that matches. Given 40 case values, and a uniform probability that the selector value will match any one of them, the if-then-elseif...endif series will average 20 comparisons.

A switch of select-case statement, on the other hand, is often compiled to machine code that uses a jump table, a list of locations of the statements using the case value as an index to the list. By converting the selector value to a position in the jump table, the select-case can jump directly to any case without comparing the selector value to any other cases. This is about a 20-fold reduction in overhead when there are 40 cases.

Practice

Note

Be sure to thoroughly review the instructions in Section 2, “Practice Problem Instructions” before doing the practice problems below.
  1. What are two possible advantages of switch and select case of a series of else ifs? Explain.

  2. What is one limitation of standard C switch statements compared with Fortran select case?

  3. Describe one feature in C switch statements that is not available in Fortran select case?

  4. What is a limitation of both C's switch and Fortran's select case?

  5. Write a C or Fortran program that implements a simple menu-driven calculator program. It should print an error message to stderr and exit with EX_DATAERR if an invalid selection is entered.

    1.. Sine
    2.. Cosine
    3.. Tangent
    9.. Quit
    
    Your selection? 1
    What is the angle in degrees? 45
    The sine is 0.707106781187.