2.2 switch 语句
1. 概念介绍
switch 语句是一种特殊的多路分支结构,它将一个变量或表达式的值与一系列 case 标签进行比较。如果匹配成功,则执行该 case 标签下的代码。它通常用于替代一长串检查同一变量是否等于多个离散值的 if-else if 语句。
2. 算法步骤
- 评估表达式: 计算
switch后面括号里表达式的值。 - 匹配
case: 将该值与每个case标签后的常量值进行比较。 - 跳转执行:
-
- 如果找到匹配的
case,程序跳转到该case标签处开始执行。 - 如果找不到任何匹配的
case,且存在default标签,则程序跳转到default处执行。 - 如果找不到匹配且没有
default,则switch语句什么也不做。
- 如果找到匹配的
- 顺序执行与
break: -
- 一旦跳转到某个
case,程序会顺序执行下去,穿透到下一个case,直到遇到break语句或switch结束。 break语句会立即跳出整个switch结构。
- 一旦跳转到某个
3. 算法可视化SVG图示 3. 算法可视化 SVG 图示
4. 核心特性
- 整型判断:
switch的表达式必须是整数类型(int,char,enum等),不能是float,double或string。 - 常量标签:
case后的值必须是编译时常量。 - 穿透行为 (Fall-through): 如果
case块末尾没有break,执行流会继续进入下一个case块,这是switch最独特的特性,既是强大功能也是常见错误源。 default子句: 可选,用于处理所有case都不匹配的情况。
5. C++代码基础实现
#include <iostream>
int main() {
int day;
std::cout << "请输入星期几 (1-7): ";
std::cin >> day;
switch (day) {
case 1:
std::cout << "星期一" << std::endl;
break;
case 2:
std::cout << "星期二" << std::endl;
break;
case 3:
std::cout << "星期三" << std::endl;
break;
case 4:
std::cout << "星期四" << std::endl;
break;
case 5:
std::cout << "星期五" << std::endl;
break;
case 6:
case 7: // 利用穿透特性
std::cout << "周末" << std::endl;
break;
default:
std::cout << "输入错误" << std::endl;
break;
}
return 0;
}
6. 优化策略
- 编译器优化: 现代编译器通常会将
switch语句优化为跳转表(Jump Table)或二分搜索,其效率通常高于等效的if-else if链。因此,当条件适用时,优先使用switch本身就是一种优化。 - 合理安排
case: 将最常见的case放在前面可能(在某些编译器实现中)有微小的性能提升,但主要还是为了代码可读性。
7. 优缺点
- 优点:
-
- 当判断同一变量与多个离散常量时,结构清晰,可读性高。
- 效率通常比
if-else if链高。 - "穿透"特性可以巧妙地用于处理多种情况执行相同代码的场景。
- 缺点:
-
- 限制性强,只能用于整型和常量判断,不能进行范围判断。
- 容易忘记写
break,导致逻辑错误。 - 每个
case都必须是唯一的常量。
8. 应用场景
- 菜单选择: 根据用户输入的数字或字符执行不同功能。
- 状态机: 根据当前状态(通常用枚举或整数表示)转移到下一个状态。
- 解析命令: 根据命令行参数或协议中的命令码执行不同操作。
- 词法分析: 在编译器或解释器中,根据读取到的字符类型进行分类处理。
9. 扩展
-
C++17
switchwith initialization: 可以在switch语句中声明和初始化一个变量,其作用域仅限于该switch块。switch (auto c = get_char(); c) { case 'a': /* ... */ break; case 'b': /* ... */ break; // c 在这里可见 } // c 在这里不可见 -
Duff's Device: 一个利用
switch穿透特性的著名C语言高级技巧,用于实现循环展开优化,但代码可读性极差,在现代C++中几乎用不到。
10. 课后配套练习
- 月份天数: 输入一个月份(1-12),输出该月份在平年有多少天(不考虑闰年)。
- 简单计算器: 输入两个整数和一个运算符(
+,-,*,/),输出计算结果。 - 成绩等级: 输入一个百分制成绩,先将其除以10取整,然后用
switch判断等级(9-10为'A', 8为'B', 7为'C', 6为'D', 其他为'F')。 - 方向控制: 输入一个字符代表方向('W'-上, 'S'-下, 'A'-左, 'D'-右),输出对应的中文方向。
- 元音辅音判断: 输入一个小写字母,判断是元音字母(a, e, i, o, u)还是辅音字母。
点击查看答案
1. 月份天数
#include <iostream>
int main() {
int month;
std::cin >> month;
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
std::cout << 31 << std::endl;
break;
case 4: case 6: case 9: case 11:
std::cout << 30 << std::endl;
break;
case 2:
std::cout << 28 << std::endl;
break;
default:
std::cout << "Invalid month" << std::endl;
break;
}
return 0;
}
2. 简单计算器
#include <iostream>
int main() {
int a, b;
char op;
std::cin >> a >> op >> b;
switch (op) {
case '+':
std::cout << a + b << std::endl;
break;
case '-':
std::cout << a - b << std::endl;
break;
case '*':
std::cout << a * b << std::endl;
break;
case '/':
if (b != 0) {
std::cout << a / b << std::endl;
} else {
std::cout << "Error: Division by zero" << std::endl;
}
break;
default:
std::cout << "Invalid operator" << std::endl;
break;
}
return 0;
}
3. 成绩等级
#include <iostream>
int main() {
int score;
std::cin >> score;
switch (score / 10) {
case 10:
case 9:
std::cout << 'A' << std::endl;
break;
case 8:
std::cout << 'B' << std::endl;
break;
case 7:
std::cout << 'C' << std::endl;
break;
case 6:
std::cout << 'D' << std::endl;
break;
default:
std::cout << 'F' << std::endl;
break;
}
return 0;
}
4. 方向控制
#include <iostream>
int main() {
char dir;
std::cin >> dir;
switch (dir) {
case 'W':
case 'w':
std::cout << "上" << std::endl;
break;
case 'S':
case 's':
std::cout << "下" << std::endl;
break;
case 'A':
case 'a':
std::cout << "左" << std::endl;
break;
case 'D':
case 'd':
std::cout << "右" << std::endl;
break;
default:
std::cout << "无效输入" << std::endl;
break;
}
return 0;
}
5. 元音辅音判断
#include <iostream>
int main() {
char c;
std::cin >> c;
switch (c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
std::cout << "元音" << std::endl;
break;
default:
std::cout << "辅音" << std::endl;
break;
}
return 0;
}
11. 相关网络资源推荐
- cppreference.com - switch statement
- OI Wiki - 分支结构 (含switch)
- learncpp.com - Switch statements