Switch Statements
When you need to compare one variable against many possible values, a switch statement is cleaner and often faster than a long if-else if chain. C++ switch works with integer types, char, and enum — not floating-point or std::string (directly).
Basic Switch
#include <iostream>
using namespace std;
int main() {
int day = 3;
switch (day) {
case 1:
cout << "Monday\n";
break;
case 2:
cout << "Tuesday\n";
break;
case 3:
cout << "Wednesday\n";
break;
case 4:
cout << "Thursday\n";
break;
case 5:
cout << "Friday\n";
break;
case 6:
cout << "Saturday\n";
break;
case 7:
cout << "Sunday\n";
break;
default:
cout << "Invalid day\n";
}
// Output: Wednesday
return 0;
}Warning: Each case must end with a break statement. Without break, execution falls through to the next case. This is the most common switch mistake.
The break and default
#include <iostream>
using namespace std;
int main() {
int choice = 5;
switch (choice) {
case 1:
cout << "One\n";
break;
case 2:
cout << "Two\n";
break;
default:
// default runs if no case matches
cout << "Unknown choice: " << choice << "\n";
break; // Optional in the last case, but add for consistency
}
// Output: Unknown choice: 5
return 0;
}The default case can appear anywhere in the switch but is conventionally placed last.
Intentional Fall-Through
Sometimes you want fall-through to handle multiple cases identically:
#include <iostream>
using namespace std;
int main() {
int month = 4; // April
// Grouped cases — share the same code block
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
cout << "31 days\n";
break;
case 4:
case 6:
case 9:
case 11:
cout << "30 days\n";
break;
case 2:
cout << "28 or 29 days\n";
break;
default:
cout << "Invalid month\n";
}
// Output: 30 days
return 0;
}In C++17 you can annotate intentional fall-through with [[fallthrough]] to silence compiler warnings:
switch (x) {
case 1:
doSomething();
[[fallthrough]]; // Intentional — suppresses warning
case 2:
doSomethingElse();
break;
}Switch with char
#include <iostream>
using namespace std;
int main() {
char grade = 'B';
switch (grade) {
case 'A':
cout << "Excellent!\n";
break;
case 'B':
cout << "Good job!\n";
break;
case 'C':
cout << "Satisfactory.\n";
break;
case 'D':
cout << "Needs improvement.\n";
break;
case 'F':
cout << "Failing.\n";
break;
default:
cout << "Invalid grade.\n";
}
// Output: Good job!
return 0;
}Switch with Enum
Combining switch with enum is idiomatic C++ — the compiler warns if you miss a case:
#include <iostream>
using namespace std;
enum class Direction { NORTH, SOUTH, EAST, WEST };
string describe(Direction d) {
switch (d) {
case Direction::NORTH: return "Moving north";
case Direction::SOUTH: return "Moving south";
case Direction::EAST: return "Moving east";
case Direction::WEST: return "Moving west";
// No default — compiler warns if a new Direction is added and unhandled
}
return "Unknown";
}
int main() {
cout << describe(Direction::NORTH) << "\n"; // Moving north
cout << describe(Direction::EAST) << "\n"; // Moving east
return 0;
}Switch with Initialiser (C++17)
Like if, C++17 allows an initialiser in the switch:
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, int> commands = {
{"start", 1}, {"stop", 2}, {"pause", 3}
};
string input = "start";
// Initialise 'it' scoped to the switch block
switch (auto it = commands.find(input); (it != commands.end()) ? it->second : 0) {
case 1:
cout << "Starting...\n";
break;
case 2:
cout << "Stopping...\n";
break;
case 3:
cout << "Pausing...\n";
break;
default:
cout << "Unknown command.\n";
}
// Output: Starting...
return 0;
}Switch vs if-else: When to Use Which
| Situation | Use |
|---|---|
| Integer / char / enum with many values | switch |
Range-based comparisons (> 10, < 20) | if-else |
| Floating-point comparisons | if-else |
| String comparisons | if-else (or map lookup) |
| Two or three conditions | Either (if-else simpler) |
| Complex Boolean logic | if-else |
Strings in Switch — The Workaround
C++ switch does not support strings directly. Use an unordered_map for O(1) dispatch:
#include <iostream>
#include <unordered_map>
#include <functional>
#include <string>
using namespace std;
int main() {
unordered_map<string, function<void()>> handlers = {
{"help", []{ cout << "Showing help...\n"; }},
{"quit", []{ cout << "Quitting...\n"; }},
{"status", []{ cout << "System OK\n"; }},
};
string command = "status";
if (auto it = handlers.find(command); it != handlers.end()) {
it->second(); // Call the handler
} else {
cout << "Unknown command: " << command << "\n";
}
// Output: System OK
return 0;
}Practical Example: Simple Calculator
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a, b;
char op;
cout << "Enter: number operator number (e.g., 10 + 5): ";
cin >> a >> op >> b;
double result = 0.0;
bool valid = true;
switch (op) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
case 'x':
case 'X':
result = a * b;
break;
case '/':
if (b == 0) {
cout << "Error: division by zero\n";
valid = false;
} else {
result = a / b;
}
break;
case '%':
if (b == 0) {
cout << "Error: modulo by zero\n";
valid = false;
} else {
result = fmod(a, b);
}
break;
case '^':
result = pow(a, b);
break;
default:
cout << "Error: unknown operator '" << op << "'\n";
valid = false;
}
if (valid) {
cout << a << " " << op << " " << b << " = " << result << "\n";
}
return 0;
}
// Example run:
// Enter: number operator number: 10 / 4
// 10 / 4 = 2.5
//
// Enter: number operator number: 2 ^ 8
// 2 ^ 8 = 256Summary
switchdispatches to acasebased on an integer/char/enum value — cleaner than longif-else ifchains- Every
casemust end withbreak— without it, execution falls through to the next case - Group cases with empty case bodies to share a code block (intentional fall-through)
- Use
[[fallthrough]]in C++17 to document intentional fall-through and suppress warnings defaultruns if no case matches — always include it to handle unexpected valuesswitchdoes not work withdoubleorstd::stringdirectly — useif-elseor a map- Prefer
switchwith enum class — the compiler warns you when a new enum value is unhandled
Next, we'll learn about for loops — how to repeat operations a fixed number of times and iterate over collections.