Switch Statement
COS1511 - Introduction To Programming I · Learning C++
Switch Statement
Basic Syntax
A switch statement allows you to evaluate a single expression and select one of many code paths based on its value. The basic structure of a switch statement is as follows:
switch (expression) {
case value1:
// code for value1
break;
case value2:
// code for value2
break;
case value3:
// code for value3
break;
default:
// code if no case matches
break; // optional but good practice
}The components of the switch statement are:
- switch (expr): Evaluates expr and jumps to the matching case. This is required.
- case value:: A label for a specific constant value. At least one case is required.
- break;: Exits the switch block immediately. It is strongly recommended to include this.
- default:: A catch-all label that runs when no case matches. This is optional but best practice.
Valid Expression Types
The expression in a switch statement must evaluate to an integral or enumeration type. The case values must be compile-time constants. Valid types include:
- int, short, long, long long (and their unsigned variants)
- char (treated as its ASCII integer value)
- enum types
Invalid types include float, double, string, or any non-constant case value.
How It Works
When a switch statement runs, the expression is evaluated once. The program scans the case labels from top to bottom until it finds a match. It then jumps to that label and begins executing statements from that point forward.
Step-by-step Example — Day of the Week
#include <iostream>
using namespace std;
int main() {
int day = 3;
switch (day) { // step 1: evaluate 'day' -> 3
case 1: // step 2: 3 == 1? No, skip
cout << "Monday";
break;
case 2: // step 3: 3 == 2? No, skip
cout << "Tuesday";
break;
case 3: // step 4: 3 == 3? YES -> jump here
cout << "Wednesday";
break; // step 5: break -> exit switch
case 4:
cout << "Thursday";
break;
default:
cout << "Weekend or invalid";
break;
}
return 0;
}The output of this code will be:
WednesdayThe steps of execution are:
- Evaluate switch expression: day = 3
- Compare 3 with case 1: no match, skip
- Compare 3 with case 2: no match, skip
- Compare 3 with case 3: MATCH — jump to this label
- Execute: cout << "Wednesday"
- Hit break — exit the entire switch block
- Continue program after the closing }
The break Statement
The break statement tells C++ to exit the switch block immediately. Without break, execution continues into the next case. This behaviour is known as fall-through.
Example of Unintentional Fall-through
int choice = 2;
switch (choice) {
case 1:
cout << "One" << endl;
// no break!
case 2:
cout << "Two" << endl;
// no break!
case 3:
cout << "Three" << endl;
// no break!
default:
cout << "Default" << endl;
}
// Output: Two
// Three
// Default <-- all three ran!Watch out: Without break, execution falls through every subsequent case until it hits a break or the closing brace. This is almost always a bug when unintentional.
Example with Break — Correct Behaviour
int choice = 2;
switch (choice) {
case 1:
cout << "One" << endl;
break; // exits after case 1
case 2:
cout << "Two" << endl;
break; // exits after case 2
case 3:
cout << "Three" << endl;
break;
default:
cout << "Default" << endl;
break;
}
// Output: TwoThe default Case
The default label acts as a catch-all. It runs when the switch expression does not match any of the listed case values. Although it is optional, it is strongly recommended for robust error handling.
Example — Menu Input Validation
#include <iostream>
using namespace std;
int main() {
int option;
cout << "Enter 1, 2, or 3: ";
cin >> option;
switch (option) {
case 1:
cout << "You chose: New Game" << endl;
break;
case 2:
cout << "You chose: Load Game" << endl;
break;
case 3:
cout << "You chose: Exit" << endl;
break;
default:
cout << "Invalid option. Please enter 1, 2, or 3." << endl;
break;
}
return 0;
}The default can appear anywhere in the switch, but placing it last is the universal convention for readability.
Fall-through Behaviour
Fall-through can be used intentionally to run the same code for multiple case values. When you deliberately omit break, always add a comment to indicate that it is intentional.
Example — Season Classifier
int month = 4; // April
switch (month) {
case 12:
case 1:
case 2:
cout << "Winter" << endl;
break;
case 3:
case 4: // month == 4 matches here, falls to case 5
case 5:
cout << "Spring" << endl; // <-- this runs
break;
case 6:
case 7:
case 8:
cout << "Summer" << endl;
break;
case 9:
case 10:
case 11:
cout << "Autumn" << endl;
break;
default:
cout << "Invalid month" << endl;
break;
}
// Output: SpringGrouping Cases
Grouping is a clean way to apply one block of code to several values. Stack the case labels immediately above the shared code. No statements between them means controlled fall-through.
Example — Vowel / Consonant Checker
char letter = 'e';
switch (letter) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
cout << letter << " is a vowel." << endl;
break;
default:
cout << letter << " is a consonant." << endl;
break;
}
// Output: e is a vowel.Example — Weekday / Weekend
int day = 6; // Saturday
switch (day) {
case 1: case 2: case 3: case 4: case 5:
cout << "Weekday" << endl;
break;
case 6: case 7:
cout << "Weekend" << endl; // <-- runs
break;
default:
cout << "Invalid day" << endl;
break;
}
// Output: Weekendswitch vs if-else
Both switch and if-else handle multi-way branching, but each has its strengths. Use switch when matching one variable against a list of known constant values. Use if-else for ranges, multiple variables, or complex boolean expressions.
Side-by-side Code Comparison
// switch — clean for exact integer/char matches
switch (grade) {
case 'A': cout << "Excellent"; break;
case 'B': cout << "Good"; break;
case 'C': cout << "Average"; break;
default: cout << "Below avg"; break;
}
// if-else — required for range-based logic
if (score >= 90) cout << "Excellent";
else if (score >= 75) cout << "Good";
else if (score >= 60) cout << "Average";
else cout << "Below avg";Common Pitfalls
Watch out: Forgetting break can lead to unintentional fall-through, which is a common bug.
// BUG: missing break in case 1
switch (x) {
case 1:
cout << "One" << endl;
// forgot break!
case 2:
cout << "Two" << endl; // also runs when x == 1!
break;
}
// Fix: add break; at the end of every caseWatch out: Duplicate case values will cause a compile error.
// BUG: two cases with value 2 — compile error!
switch (n) {
case 2: cout << "First"; break;
case 2: cout << "Second"; break; // ERROR
}
// Fix: each case value must be uniqueWatch out: Using float or string as the switch expression is not allowed.
double price = 9.99;
// BUG: float is not allowed in switch
switch (price) { // compile error!
case 9.99: ...
}
string name = "Alice";
// BUG: string is not allowed in switch
switch (name) { // compile error!
case "Alice": ...
}
// Fix: use if-else for floats and stringsWatch out: Declaring variables inside case without braces can lead to scope issues.
// BUG: variable declaration jumps over by another case
switch (x) {
case 1:
int y = 10; // compile error in some compilers
cout << y;
break;
case 2:
cout << "Two";
break;
}
// Fix: wrap the case body in braces
switch (x) {
case 1: {
int y = 10;
cout << y;
break;
}
case 2:
cout << "Two";
break;
}Summary
- Always end every case with break; unless fall-through is intentional.
- Always include a default: case to handle unexpected values.
- Use switch for exact constant matches — use if-else for ranges and complex conditions.
- Comment intentional fall-through clearly.
- Wrap case bodies in { } whenever you declare local variables inside them.
- Each case value must be unique.
Check your understanding
- What is the purpose of the break statement in a switch case?
- When should you use a default case in a switch statement?
- How can you intentionally create fall-through behaviour in a switch statement?
- What types of expressions are allowed in a switch statement?