Skip to content

第 10 章 选项太多怎么办——switch 与三目


🏗️ 前情回顾:上章你问了「两个岔路口够用——但如果选项有七八个呢?」这一章就是答案。switch-case 处理「多选一」干净利落,三目运算符 ? : 让你一句话搞定简单的二选一。


🎯 本章目标

学完这一章,你能:

  • switch-case 写出清晰的多分支代码
  • 理解 break 的作用——阻止"穿透"
  • 知道什么时候该用 default 兜底
  • 用三目运算符 ? : 简洁地表达"二选一"
  • 判断什么时候用 switch-case、什么时候用 if-else

📖 故事引入

放学后你走到自动售货机前,想买瓶饮料。

机器屏幕上显示菜单:1-可乐、2-雪碧、3-芬达、4-矿泉水、5-果汁……

你按了"3",机器"咕咚"一声掉出一瓶芬达。

这个过程的代码逻辑大概是:

如果 选了 1 → 出可乐
如果 选了 2 → 出雪碧
如果 选了 3 → 出芬达
...

else if 写也能搞定,但你要是看代码——密密麻麻一排 else if,像一堵墙。而且每次判断都要把"选了哪个数字"重新算一遍,不够利索。

有没有一种写法,直接告诉程序:"看这个数字是多少,跳到对应入口"?

有,这就是 switch-case


🧱 知识讲解

10.1 switch-case 基本语法

switch-case 就像一个"跳转表"——你给一个整数(或字符),程序直接跳到对应的 case 标签开始执行:

cpp
switch (表达式) {
    case 值1:
        // 表达式 == 值1 时执行这里
        break;
    case 值2:
        // 表达式 == 值2 时执行这里
        break;
    default:
        // 所有 case 都不匹配时执行这里
}

自动售货机的例子:

cpp
int choice;
cin >> choice;

switch (choice) {
    case 1:
        cout << "你选了:可乐" << endl;
        break;
    case 2:
        cout << "你选了:雪碧" << endl;
        break;
    case 3:
        cout << "你选了:芬达" << endl;
        break;
    case 4:
        cout << "你选了:矿泉水" << endl;
        break;
    case 5:
        cout << "你选了:果汁" << endl;
        break;
    default:
        cout << "没有这个编号,请重新选择" << endl;
}

对比 else if 版本,switch-case 的好处一目了然:结构清晰,一眼就能看出有多少个选项,每个选项做什么。

10.2 break 的作用:制止"穿透"

❌ 先看看这段代码——有什么问题?

cpp
int n = 2;
switch (n) {
    case 1: cout << "A";
    case 2: cout << "B";
    case 3: cout << "C";
}
// 输出:BC  ← 嗯?怎么 B 和 C 都出来了?

输入 2,期望只输出 "B",结果 "BC" 都出来了!这是因为 switch-case 有个特别的设计——case 标签只是"入口",不是"出口"。程序从匹配的 case 冲进去,然后就一路向下狂奔,把后面的 case 全执行一遍,直到遇到 break 或 switch 结束。

这叫做穿透——不加 break,程序就像瀑布一样从当前 case 一路流到底。

✅ 正确版本:每个 case 末尾加 break

cpp
int n = 2;
switch (n) {
    case 1:
        cout << "A" << endl;
        break;
    case 2:
        cout << "B" << endl;    // 输出 B
        break;                  // 然后跳出,不往下掉
    case 3:
        cout << "C" << endl;
        break;
}
// 输出:B  ← 这才是我们要的

💡 穿透是 bug 的温床。除非你刻意利用穿透(下一节会讲),否则每个 case 末尾都加 break

10.3 巧用穿透:合并相同处理

有时候多个 case 做同样的事,利用穿透可以写得非常漂亮:

cpp
int month;
cin >> month;

switch (month) {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        cout << "31天" << endl;
        break;
    case 4: case 6: case 9: case 11:
        cout << "30天" << endl;
        break;
    case 2:
        cout << "28天或29天" << endl;
        break;
    default:
        cout << "无效月份" << endl;
}

看!1、3、5、7、8、10、12 月都是 31 天,写在一排 case 标签里,共享同一段代码。这比 if (month==1 || month==3 || ...) 清爽多了。

另一个常用场景——成绩等级简化版:

cpp
int score;
cin >> score;

switch (score / 10) {   // 除以 10 取整:95→9,82→8,67→6
    case 10:            // 100 分
    case 9:
        cout << "A" << endl;
        break;
    case 8:
        cout << "B" << endl;
        break;
    case 7:
        cout << "C" << endl;
        break;
    case 6:
        cout << "D" << endl;
        break;
    default:
        cout << "E" << endl;
}

💡 这里 score / 10 是整数除法,能把分数映射到 0–10 的区间,再用 switch 一锤定音。这是 switch 的经典用法。

10.4 switch-case 的限制

switch 不是万能的,它有明确的限制:

  1. switch 后面的表达式必须是整型或字符型intlong longchar,以及后面会学的枚举)。不能是 double、不能是 string

  2. case 后面必须是常量——不能是变量,不能是范围(你不能写 case 60..100:)。

  3. 各 case 的值不能重复——编译器直接报错。

这些限制意味着:switch-case 适合"精确匹配某个值"的场景。如果你需要判断"分数 > 90",那还是用 if-else

10.5 三目运算符 ? ::最简单的二选一

有时候你要做的判断非常简单——就一行赋值:

cpp
// if-else 写法
int result;
if (a > b) {
    result = a;
} else {
    result = b;
}

天哪,写了 5 行就为了取个最大值。C++ 有个更简洁的写法——三目运算符 ? :

cpp
int result = (a > b) ? a : b;   // 一行搞定!

格式:

条件 ? 成立时的值 : 不成立时的值

翻译成人话:"条件成立吗?成立就选冒号前面的,不成立就选冒号后面的。"

更多例子:

cpp
int absValue = (x >= 0) ? x : -x;                    // 求绝对值
string status = (score >= 60) ? "及格" : "不及格";   // 输出文字
cout << ((n % 2 == 0) ? "偶数" : "奇数") << endl;     // 直接输出

⚠️ 三目运算符不要嵌套!a ? b : c ? d : e 这种写法只有写的人自己能看懂(过三天自己也不一定看得懂)。简单二选一用它,复杂的请老老实实写 if-else

10.6 switch-case vs if-else:怎么选

场景推荐原因
判断范围(> <)if-elseswitch 不支持范围
精确匹配几个值switch-case结构更清晰
条件涉及逻辑运算if-elseswitch 里不能写 &&
选项很多(5+)switch-case代码更整洁
简单二选一赋值三目 ? :一行搞定

没有绝对的优劣,选让代码更清晰好读的那个。


✋ 动手试试

试试 1:写一个程序,输入 1–7 的数字,输出对应的星期几(1→星期一,2→星期二……)。用 switch-case

试试 2:把第 9 章的成绩评级程序(A/B/C/D/E)用 switch-case 改写一遍。对比两种写法,你更喜欢哪个?

试试 3:用三目运算符写一个"判断奇偶"的程序——输入一个整数,输出"奇数"或"偶数"。只用一行 cout

试试 4:故意不给每个 case 写 break,观察"穿透"现象。比如输入 2,看看哪些 case 被执行了。


⚠️ 你踩过这些坑吗

  • [ ] 坑 1:忘了写 break——程序从匹配的 case 一路执行到底,把后面的 case 代码也跑了。每个 case 末尾加 break,除非你故意的。
  • [ ] 坑 2:用 switch 判断范围——case 60..100: 不合法,范围判断用 if-else
  • [ ] 坑 3:switch 里用 string——switch (name) { case "小明": ... } C++ 不支持,字符串比较用 if-else
  • [ ] 坑 4:三目运算符写得太复杂——int r = a > b ? (c > d ? e : f) : (g > h ? i : j); 谁能看懂?三目只做简单二选一,复杂的回到 if-else

📝 练习

基础题

1. 选择题

(1)以下 switch 语句中,n = 2 时输出什么?

cpp
switch (n) {
    case 1: cout << "A"; break;
    case 2: cout << "B";
    case 3: cout << "C"; break;
    default: cout << "D";
}

A. B   B. BC   C. C   D. BCD

(2)int m = (x > y) ? x : y; 这行代码的作用是:
A. 判断 x 是否大于 y   B. 把较大的值赋给 m   C. 交换 x 和 y   D. 比较 x 和 y 是否相等

(3)以下哪个不能放在 switch 后面的括号里?
A. int 变量   B. char 变量   C. string 变量   D. 算术表达式

2. 填空题

(1)switch 语句中,_________ 关键字用于阻止穿透。

(2)_________ 关键字用于处理所有 case 都不匹配的情况。

(3)x > 0 ? 1 : -1 的结果:当 x = 5 时是 ___,当 x = -3 时是 ___

3. 代码找错

以下代码有什么问题?修改成正确的版本:

cpp
int day;
cin >> day;
switch (day) {
    case 1: cout << "星期一";
    case 2: cout << "星期二";
    case 3: cout << "星期三";
}

4. 读代码写输出

cpp
int n = 8;
cout << (n % 2 == 0 ? "YES" : "NO") << endl;

写出上面代码的输出结果:_________

提高题

5. 编程题 — 简易计算器(switch 版)

switch-case 改写第 9 章的计算器程序。输入两个整数和一个运算符(+ - * /),用 switch 判断运算符,输出结果。除数为 0 时提示错误。

6. 编程题 — 季节判断

输入月份(1–12),输出对应的季节:

  • 3–5 月:春天
  • 6–8 月:夏天
  • 9–11 月:秋天
  • 12、1、2 月:冬天

用 switch-case 的穿透特性,尽量用最少的代码。

7. 编程题 — 成绩评级(完整版)

输入一个 0–100 的分数:

  • 如果是有效的分数(0~100),用 switch 输出等级 A/B/C/D/E
  • 如果无效,输出"分数不合法"
  • 额外:如果分数是 100 分,输出"满分!太厉害了!"

挑战题

8. 编程题 — 日期合法性

输入年、月、日,判断这个日期是否合法(例如 2024-2-30 不合法)。需要考虑:

  • 大月(31 天):1、3、5、7、8、10、12
  • 小月(30 天):4、6、9、11
  • 2 月:闰年 29 天,平年 28 天

用 switch-case 处理月份,结合第 9 章的闰年判断。

9. 编程题 — 星座查询

输入月份和日期,输出对应的星座。例如:3月21日~4月19日是白羊座。用 switch-case 嵌套 if 实现。(提示:先用 switch 分月,再在每个月里用 if 判断日期范围。)


🧠 本章小结

┌─────────────────────────────────────────────────────────┐
│                                                         │
│   switch-case:给一个值,跳到对应入口                     │
│                                                         │
│   break = 出口(不加就穿透)                              │
│   default = 兜底(所有 case 都不匹配时走这里)             │
│                                                         │
│   switch 限制:只能整型/字符型,case 必须是常量            │
│                                                         │
│   三目运算符:条件 ? 成立值 : 不成立值                    │
│   → 简单二选一的神器,别嵌套!                            │
│                                                         │
│   选择指南:                                             │
│   范围判断 → if-else                                    │
│   精确匹配多值 → switch-case                            │
│   简单二选一 → 三目 ? :                                  │
│                                                         │
└─────────────────────────────────────────────────────────┘

📝 配套练习

共8题。switch语法简单——重点是"什么时候用switch vs if"。J0036(买铅笔)和J0039(电费)教分段决策的应用价值。。★核心(课堂必做) ◆拓展(课后练习)

级别题号链接覆盖知识点
★ 核心J0034https://hydro.ac/d/srqc/p/J0034switch-case、break、default
◆ 拓展J0042https://hydro.ac/d/srqc/p/J0042if-else、计数、? : 三目
◆ 拓展J0043https://hydro.ac/d/srqc/p/J0043排序、条件判断、三输出
◆ 拓展luogu-B2048https://hydro.ac/p/luogu-B2048switch、分段计费
◆ 拓展J0032https://hydro.ac/d/srqc/p/J0032if-else链、BMI分段
◆ 拓展J0036https://hydro.ac/d/srqc/p/J0036if-else、最小值、三选一
◆ 拓展J0039https://hydro.ac/d/srqc/p/J0039分段计费、else-if链、边界
◆ 拓展luogu-B2050https://hydro.ac/p/luogu-B2050if-else、三角形条件、逻辑&&

💡 练习建议:先完成 1 道★核心题,确保掌握本章基本方法;再完成 7 道◆拓展题,覆盖不同变式和细节。


配套练习

共8题。switch语法简单——重点是"什么时候用switch vs if"。J0036(买铅笔)和J0039(电费)教分段决策的应用价值。★核心(课堂必做) · ◆拓展(课后练习)

级别题号链接覆盖知识点
★ 核心J0034https://hydro.ac/d/srqc/p/J0034switch-case、break、default
◆ 拓展J0042https://hydro.ac/d/srqc/p/J0042if-else、计数、? : 三目
◆ 拓展J0043https://hydro.ac/d/srqc/p/J0043排序、条件判断、三输出
◆ 拓展luogu-B2048https://hydro.ac/p/luogu-B2048switch、分段计费
◆ 拓展J0032https://hydro.ac/d/srqc/p/J0032if-else链、BMI分段
◆ 拓展J0036https://hydro.ac/d/srqc/p/J0036if-else、最小值、三选一
◆ 拓展J0039https://hydro.ac/d/srqc/p/J0039分段计费、else-if链、边界
◆ 拓展luogu-B2050https://hydro.ac/p/luogu-B2050if-else、三角形条件、逻辑&&

练习建议:先在课堂完成 1 道★核心题,掌握本章基本方法;课后完成 7 道◆拓展题,覆盖不同变式和细节。

自查清单

  • [ ] 我能写出带 breakdefault 的 switch-case 语句
  • [ ] 我理解"穿透"——知道什么时候故意用它,什么时候必须加 break
  • [ ] 我知道 switch-case 的限制(不能是 string,不能是范围)
  • [ ] 我会用三目运算符 ? : 做简单的二选一
  • [ ] 我能根据场景选择 switch-case 还是 if-else

🚀 下章预告:判断一次就跑太浪费了——同一件事做 100 遍,才是计算机真正的强项。下章学 for 循环,3 行代码干 100 行的活。