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.
What are two possible advantages of switch
and
select case
of a series of else if
s?
Explain.
What is one limitation of standard C switch
statements
compared with Fortran select case
?
Describe one feature in C switch
statements
that is not available in Fortran select case
?
What is a limitation of both C's switch
and
Fortran's select case
?
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.