One Value, Many Cases

An if ladder asks a sequence of yes-or-no questions. A switch asks one question, "which of these constants is the value equal to", and jumps straight to the matching case. Chapter 5 gave the rules: the selector is an integer or a character, each label is a constant, every case ends in break unless you mean it to fall into the next, and default catches everything else. Week 7 is three programs whose whole structure is a switch, chosen because each one shows a different habit: twelve plain cases, stacked labels with a guard inside a case, and character labels with a library call in default.

Program 1: The Month in Words

Read a month number from 1 to 12 and print its name.

Algorithm:

  1. Start.
  2. Read the month number.
  3. Select on the number: 1 prints January, 2 prints February, and so on to 12 for December.
  4. If no case matches, print that the month is invalid.
  5. Stop.

Twelve cases, twelve breaks, one default. Delete the break after case 3 and run it with 3: March prints, and then April prints too, because without break execution falls straight through into the next case, and GCC even warns that the statement may fall through. That is the bug the examiner is looking for, and it is why every case here ends in break even though the last one before default does not strictly need it: the day someone adds a case after it, the missing break becomes a fallthrough. default returns rather than breaking, because an invalid month is a failure of the program, not a thirteenth month.

Chapter 8 offered the alternative, a table of twelve strings indexed by month - 1 after a range check. It is shorter and it is what a working program would do; the switch is what the syllabus asks for, and it is the right answer when the cases do more than look up a word.

Program 2: A Calculator with switch

Read an integer, an operator, and another integer, in the form 12 + 5, and print the result. The operators are +, -, x or * for multiplication, /, and %.

Algorithm:

  1. Start.
  2. Read the first operand, the operator character, and the second operand.
  3. Select on the operator: + adds, - subtracts, x or * multiplies, / divides, % takes the remainder.
  4. For / and %, if the second operand is 0, print that division is impossible and stop.
  5. If the operator matches no case, print that it is unknown and stop.
  6. Print the expression and its result.
  7. Stop.

Try 12 + 5, 6 x 7, 7 / 2, and 5 / 0. Three habits are on show. The two labels case 'x': and case '*': stacked with nothing between them are the one form of fallthrough that is not a bug: they say two selectors share one body, and every reader recognises the shape. The zero check sits inside the / and % cases, because it only applies to them; putting it before the switch would refuse 5 + 0. And the result is printed once, after the switch, rather than in every case, so the output format lives in one place.

The %c in the format string has a space before it. scanf skips whitespace before %d on its own, but not before %c, which reads the very next character even if it is a blank; the space in the format tells it to skip blanks first. Without it op would receive the blank after 12, the %d that follows would then fail on the +, and the program would report invalid input. The operands are integers because % needs them, so 7 / 2 is 3, week 1's truncation; a calculator on double would read %lf and replace the % case with fmod from <math.h>.

Program 3: Vowel or Consonant

Read one character and say whether it is a vowel, a consonant, or not a letter at all.

Algorithm:

  1. Start.
  2. Read the character.
  3. Select on it: any of a, e, i, o, u, in either case, is a vowel.
  4. Otherwise, if it is a letter it is a consonant; if not, say so.
  5. Stop.

Ten stacked labels cover the vowels in both cases, the same shape as the calculator's x and *. Everything else lands in default, which has a decision of its own to make, consonant or non-letter, and makes it with isalpha from <ctype.h> rather than with a hand-written range test. ch >= 'a' && ch <= 'z' assumes the letters are contiguous in the character set, which ASCII promises and C does not; isalpha is right on every machine. The cast to unsigned char is the small print of <ctype.h>: its functions are defined for values 0 to 255 and EOF, and a plain char holding a byte above 127 can be negative on this platform, so the cast keeps the argument in range. For letters and digits the cast changes nothing; it is there for the input you did not expect.

The default case ends in break like every other, and a switch on a char cannot use ranges: case 'a' ... 'z': is a GCC extension that no published C standard includes, and -pedantic-errors rejects it. Enumerating the ten vowels is the standard-conforming answer.

Key Takeaways

  • A switch selects on an integer or character and jumps to the matching constant case; every case ends in break, or the next case runs too.
  • Always write default; for an impossible value it reports the failure rather than silently doing nothing.
  • Stacked labels with no statements between them share one body: case 'x': case '*': is the one fallthrough that is not a bug.
  • A guard that applies to only some cases belongs inside those cases, not before the switch.
  • " %c" with a leading space skips blanks before reading a character; bare %c does not.
  • Test letters with isalpha((unsigned char) ch), not a range on the character code; case ranges in labels are a compiler extension, not standard C.