Lesson 3 — Switch and the Conditional Operator

← Module home · ← Lesson 2 — Conditions · Lesson 4 — Requirements →

In this lesson you will learn


1. switch — routing on one value

An else-if ladder asks a different question at every step. A switch asks one question once — what is this expression’s value? — and jumps straight to the matching case:

switch (menuChoice)              // the router: one expression, evaluated once
{
    case 1:                      // a label, not a question
        std::cout << "New game\n";
        break;                   // exit the switch here
    case 2:
        std::cout << "Load game\n";
        break;
    case 3:
        std::cout << "Quit\n";
        break;
    default:                     // no label matched
        std::cout << "Invalid choice\n";
}

Reading the parts:

What may go in the switch and case values (the honest fine print for beginners):

These restrictions are why the “switch vs ladder” choice usually makes itself (§5).

2. A realistic example — menu + char router

switch shines with small fixed menus. char is a first-class router because keyboard choices are characters:

#include <iostream>
int main() {
    char cmd;
    std::cout << "Enter command (a = add, d = delete, l = list, q = quit): ";
    std::cin >> cmd;                      // >> skips spaces, reads one char

    switch (cmd)
    {
        case 'a':
            std::cout << "Adding record...\n";
            break;
        case 'd':
            std::cout << "Deleting record...\n";
            break;
        case 'l':
            std::cout << "Listing records...\n";
            break;
        case 'q':
            std::cout << "Bye!\n";
            break;
        default:
            std::cout << "Unknown command: " << cmd << '\n';
    }
    return 0;
}

Note 'a' not "a" — a char label uses single quotes (double quotes make a string, and strings can’t label a switch). Also note the default echoing the bad input back — a tiny detail that makes mis-typed commands debuggable.

3. Fallthrough — the default behaviour you must defeat

Without break, the program does not stop at the next label — it falls through and executes everything below until a break or the closing brace:

switch (level) {
    case 1:
        std::cout << "Steel ";
    case 2:
        std::cout << "Bronze ";
    case 3:
        std::cout << "Silver ";
        break;
    case 4:
        std::cout << "Gold\n";
}
// level 2 prints "Bronze Silver" — labels are doors, breaks are walls

Mnemonic: labels are doors, breaks are walls. Every case that shouldn’t leak gets a wall. GCC’s -Wimplicit-fallthrough (in -Wextra) warns when a case leaks — another reason the course compiles with -Wall -Wextra.

4. Intentional fallthrough — the stacking trick

Fallthrough is a feature when several values should share one body. Stack empty cases, then break once:

switch (month)
{
    case 12: case 1: case 2:          // winter: three labels, one wall
        std::cout << "Winter\n";
        break;
    case 3: case 4: case 5:
        std::cout << "Spring\n";
        break;
    case 6: case 7: case 8:
        std::cout << "Summer\n";
        break;
    case 9: case 10: case 11:
        std::cout << "Autumn\n";
        break;
    default:
        std::cout << "Invalid month\n";
}

The stacked labels mean “any of these values enters here”. This is the one fallthrough pattern that reads clearly; anything cleverer usually deserves a ladder instead. (An equivalent ladder with month == 12 || month == 1 || month == 2 is also fine — compare them in exercise E14.)

Legacy syntax you may see in older books: switch (x) { case 1: { ... } break; } — the braces group statements but don’t stop fallthrough; the break still does.

5. Switch vs ladder vs ?: — choosing honestly

Situation Reach for
one variable compared to several exact values (menu, command, digit, month) switch — labels document the value set, default catches the rest
ranges (>= 80), mixed variables, double/string conditions else-if ladder — switch legally cannot
two-way choice producing a value if-else, or ?: when it fits on one line (§7)
compound conditions (&&/||) if / ladder — case labels can’t hold them
many conditions on different variables chain of ifs — a switch routes on exactly one

A fair rule of thumb: if you can’t write the case labels as plain constants, you can’t write it as a switch. Everything else is style — and the compiler won’t convert a bad choice into a warning, so the test table (Lesson 2 §5) remains the referee.

6. The conditional operator ?: — a decision that yields a value

if-else is a statement — it runs code. The conditional operator is an expression — it produces a value, so it can live inside an output, an assignment, or an argument:

condition ? valueIfTrue : valueIfFalse
int max = (a > b) ? a : b;

std::cout << "You " << (marks >= 40 ? "PASS" : "FAIL") << '\n';

Read the second line as: “marks >= 40 ? then the string is PASS, otherwise FAIL.” The parentheses around the whole ?: are required here — without them << grabs marks first and the types stop matching. This is the exact upgrade the I/O module’s Lab 1 extension promised: Result: true/false becomes Result: PASS/FAIL in one line.

Two honest warnings:

With bool, one ternary is redundant: (passed ? "true" : "false") prints the same as just printing passed (bool prints as 1/0 unless you use the stream trick from I/O Lesson 1 §7 — compare both forms in P9).

7. Common switch/ternary mistakes

# Mistake Symptom Fix
S1 missing break output runs into the next case’s text wall every non-stacked case
S2 case "sun": (string) won’t compile — strings can’t label switch on char, or use a ladder
S3 case grade >= 80: won’t compile — labels are constants ladder for ranges
S4 switch on double/std::string router won’t compile ladder
S5 shared variable accidentally shadowed in two cases (same name declared in two cases) compile error — cases share one scope put each case’s body in { }, or declare before the switch
S6 no default on a menu bad input silently does nothing default + feedback
S7 ternary without outer parentheses in a stream compile error or wrong precedence wrap the whole ?:
S8 ternary with side effects (x > 0 ? x = 1 : x = 2;) confusing, error-prone if-else for actions

Recap — you can now

Next: Lesson 4 — From requirements to decisions: the full discipline — decision tables, flowcharts, pseudocode, C++, dry runs — the same five-stage pipeline the labs demand.