Initial commit: C++ courseware
This commit is contained in:
commit
4a4ee7c287
1789 files changed
+373489
No files matched your search
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,89 @@
|
||||
### **C++ 讲义:多分支选择 (`if-else if-else`)**
|
||||
|
||||
#### **一、 处理“多选一”与“互斥”**
|
||||
|
||||
**1.1 从二元选择到多元选择**
|
||||
|
||||
我们已经掌握了:
|
||||
* **`if` 结构(单分支)**:解决“做或不做”的问题。
|
||||
* **`if-else` 结构(双分支)**:解决“二选一”的问题。
|
||||
|
||||
然而,程序设计中的决策往往涉及三个或更多的选项。`if-else if-else` 结构正是为了解决这类**多选一**的场景而设计的。理解该结构的关键,在于深刻理解**“互斥”**这一概念。
|
||||
|
||||
**1.2 “互斥”:`if-else if-else` 的适用点**
|
||||
|
||||
* **互斥场景(适用 `if-else if-else`):交通信号灯**
|
||||
交通信号灯的状态是典型的互斥关系:在任何特定时刻,交通灯只能处于其中一种状态(红、黄、绿),绝不可能同时既是红灯又是绿灯。**当面临必须“多选一”的排他性选项时,应使用多分支结构。**
|
||||
|
||||
* **非互斥场景(不适用多分支,应使用多个独立 `if`):自助餐取餐**
|
||||
假设在自助餐厅,有烤鸡翅、牛排、三文鱼、沙拉四个选项。这些选项是不互斥的:你拿了烤鸡翅,并不会阻止你继续拿牛排和沙拉。这些条件可以同时成立。在这种“多选多”的场景下,必须使用多个独立的 `if` 语句来判断,不能使用 `else if`(因为 `else if` 一旦命中一个,就会跳过后续所有选项)。
|
||||
|
||||
#### **二、 语法结构与执行流程**
|
||||
|
||||
**2.1 语法结构与规则**
|
||||
|
||||
```cpp
|
||||
if (条件1) {
|
||||
// 仅当 条件1 成立时执行
|
||||
} else if (条件2) {
|
||||
// 当 条件1 不成立,且 条件2 成立时执行
|
||||
} else if (条件n) {
|
||||
// ... 可以根据需要添加任意多个 else if 分支 ...
|
||||
} else {
|
||||
// 当以上所有条件都不成立时,执行此保底操作 (此分支可省略)
|
||||
}
|
||||
```
|
||||
|
||||
**结构非常灵活:**
|
||||
|
||||
* **`else if` 可以有无限个**:根据实际决策的需要,你可以在 `if` 之后添加任意多个 `else if` 分支,以覆盖所有可能的互斥选项。
|
||||
* **`else` 是可以省略的**:最后的 `else` 分支并非强制要求。如果省略了 `else`,且上方所有的 `if` 和 `else if` 条件评估均为 `false`,程序将直接跳过整个多分支结构,不执行其中的任何代码,继续向下运行。
|
||||
|
||||
**2.2 执行顺序**
|
||||
|
||||
1. **自上而下,顺序判断**:程序会严格按照从上到下的顺序,逐一评估每个 `if` 或 `else if` 的条件。
|
||||
2. **首次命中,立即跳出**:一旦某个条件被评估为 `true`,程序将执行其对应的代码块。执行完毕后,**立即跳出整个多分支结构**,后续所有的 `else if` 和 `else` 分支都会被忽略。
|
||||
3. **`else` 隐含的条件**:每一个 `else if` 语句都隐含了一个前提——**它前面的所有 `if` 和 `else if` 条件均为 `false`**。这是编写简洁代码的关键。
|
||||
|
||||
#### **三、 实战:BMI 肥胖问题评估 (书本P40 例3-7)**
|
||||
|
||||
**3.1 任务目标**
|
||||
|
||||
根据输入的体重 `m` (kg) 和身高 `h` (m),计算身体质量指数 `BMI = m / (h * h)`,并根据以下规则输出结果:
|
||||
* **规则1**:BMI < 18.5,输出 "Underweight"。
|
||||
* **规则2**:18.5 <= BMI < 24,输出 "Normal"。
|
||||
* **规则3**:BMI >= 24,输出 BMI 数值并换行输出 "Overweight"。
|
||||
|
||||
**3.2 代码实现与逻辑分析**
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
double m, h, bmi;
|
||||
cin >> m >> h;
|
||||
bmi = m / (h * h);
|
||||
if (bmi < 18.5) {
|
||||
cout << "Underweight";
|
||||
} else if (bmi < 24) { // 利用隐含的条件简写为 bmi < 24
|
||||
cout << "Normal";
|
||||
} else { // 兜底选项
|
||||
cout << bmi << endl;
|
||||
cout << "Overweight";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**3.3 代码解读**
|
||||
|
||||
在判断“正常”范围时,我们**没有写** `else if (bmi >= 18.5 && bmi < 24)`,而是简写为 `else if (bmi < 24)`。
|
||||
|
||||
**原因**:正是利用了多分支结构的**“隐含条件”**特性。程序能执行到这个 `else if`,必然是因为第一个 `if (bmi < 18.5)` 判断为假。因此,被筛选到第二层的 BMI 数据,已经天然满足了 `bmi >= 18.5` 这个条件,无需再次判断,使得代码更简洁。
|
||||
|
||||
#### **四、 知识点总结**
|
||||
|
||||
1. **明确结构适用性**:
|
||||
处理多个且选项之间**完全互斥**的决策时,使用 `if-else if-else`。处理选项可共存(如自助餐)的决策时,必须使用多个独立的 `if`。
|
||||
2. **结构灵活**:
|
||||
一个多分支结构由 1个 `if` 起头,中间可以有 **0个或任意多个** `else if`,结尾可以有 **0个或1个** `else` 组成。虽然语法上 `else` 可以省略,但建议保留作为“保底”机制,处理其他所有未被匹配到的情况。
|
||||
3. **重视书写顺序**:
|
||||
在多分支结构中,通常应优先将**最严格、最特殊**的条件放在前面,并善于利用结构自带的隐含的条件来精简后续的判断逻辑。
|
||||
Binary file not shown.
+93
@@ -0,0 +1,93 @@
|
||||
### **C++ 讲义:`if` 条件嵌套**
|
||||
|
||||
#### **一、判断中的再判断**
|
||||
|
||||
当一个判断逻辑过于复杂,无法通过单一层级的 `if-else if-else` 有效解决时,需要引入一种更强大的结构——**条件嵌套**。
|
||||
|
||||
* **定义**:**在一个 `if`、`else if` 或 `else` 的 `{}` 代码块内部,再放入另一个完整的 `if` 结构**,这就构成了条件嵌套。
|
||||
* **核心思想**:它映射了人类解决复杂问题时的“分步决策”的思维模式。**外层 `if` 负责确定一个大的前提或类别,而内层 `if` 则在此外层前提下,处理更细分的子问题。**
|
||||
|
||||
通过嵌套,我们可以将一个复杂的大问题变成了一系列更简单的小问题。
|
||||
|
||||
#### **二、语法结构与执行流程**
|
||||
|
||||
##### **2.1 基本语法**
|
||||
|
||||
条件嵌套的本质,就是将一个 `if` 语句块作为另一个 `if` 语句块的执行内容。
|
||||
|
||||
```cpp
|
||||
if (外层条件) {
|
||||
// 外层条件成立后,进入此代码块
|
||||
if (内层条件) {
|
||||
// 当 外层条件 和 内层条件 同时成立时,执行这里的代码
|
||||
} else {
|
||||
// 当 外层条件 成立,但 内层条件 不成立时,执行这里的代码
|
||||
}
|
||||
|
||||
} else { // 注意这里的 else 匹配的是 if (外层条件)
|
||||
// 当 外层条件 不成立时,执行此代码块
|
||||
// 这里也可以继续嵌套...
|
||||
}
|
||||
```
|
||||
|
||||
##### **2.2 执行流程解析**
|
||||
|
||||
计算机在执行嵌套结构时,遵循“**由外到内,层层把关**”的原则:
|
||||
|
||||
1. **判断外层条件**:首先,只看最外层的 `if` 条件。
|
||||
2. **决定是否进入**:
|
||||
* 如果外层条件为 `false`,程序将直接跳过整个外层 `{}` 代码块,不会去检查内层的 `if` 条件。
|
||||
* 如果外层条件为 `true`,程序才会进入外层代码块中,并开始判断内层的 `if` 条件。
|
||||
3. **判断内层条件**:进入内层后,判断内层的 `if-else` 结构,根据条件的真假来决定执行哪个子分支。
|
||||
|
||||
#### **三、基础用法与实例**
|
||||
|
||||
##### **3.1 场景一:会员等级与消费金额折扣**
|
||||
|
||||
**需求**:一个商场打折规则如下:
|
||||
* 必须是会员才能享受折扣,并且会员如果消费满 500 元,打 8 折;如果消费不满 500 元,打 9 折。
|
||||
* 非会员不打折。
|
||||
|
||||
**分析**:
|
||||
* **外层判断**:首要前提是“是否为会员?”
|
||||
* **内层判断**:在“是会员”这个大前提下,再细分“消费金额是否满500?” 的条件。
|
||||
|
||||
**代码实现**:
|
||||
```cpp
|
||||
bool is_member = true;
|
||||
double total_cost = 600.0;
|
||||
|
||||
if (is_member == true) {
|
||||
// 代码能进入此区域,说明此人一定是会员
|
||||
cout << "尊贵的会员您好" << endl;
|
||||
|
||||
if (total_cost >= 500) {
|
||||
// 会员,且消费满500
|
||||
cout << "享受8折优惠!" << endl;
|
||||
} else {
|
||||
// 会员,但消费未满500
|
||||
cout << "享受9折优惠!" << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
// 代码没有进入此区域,说明此人一定不是会员
|
||||
cout << "抱歉,非会员不参与打折活动。" << endl;
|
||||
}
|
||||
```
|
||||
|
||||
##### **3.2 场景二:三数排序 (书本例3-5)**
|
||||
|
||||
**任务**:输入三个整数 `a, b, c`,将它们从大到小排序输出。
|
||||
|
||||
**分析**:
|
||||
* **外层判断**:先确定三个数中最大的那个数是谁(三选一)。
|
||||
* **内层判断**:在最大数确定的前提下,只需比较剩下两个数的大小(二选一)。
|
||||
|
||||
**代码实现参见书本例3-5,本处略。**
|
||||
|
||||
#### **四、总结**
|
||||
|
||||
1. **嵌套构建复杂逻辑**:当单一维度的判断不足以解决问题时,使用 `if` 嵌套结构来处理“层层递进”的判断。
|
||||
2. **分治思想的体现**:条件嵌套是一种“分而治之”的思想。外层 `if` 解决主要矛盾,内层 `if` 解决次要矛盾,从而将复杂问题分解。
|
||||
3. **提升代码可读性**:良好的嵌套结构能让代码逻辑与人类的自然思考过程保持一致,是编写高质量、可维护代码的重要技巧。
|
||||
4. **注意代码缩进**:在编写嵌套代码时,必须使用规范的缩进,以清晰地展示代码的层级关系,否则代码将变得难以阅读和维护。
|
||||
BIN
Binary file not shown.
+34
@@ -0,0 +1,34 @@
|
||||
### **参考答案**
|
||||
|
||||
#### **一、 填空题**
|
||||
|
||||
1. 多选一
|
||||
2. 多分支, 一
|
||||
3. 保底, 不满足
|
||||
4. 条件嵌套 (或 嵌套分支 / 分支嵌套)
|
||||
5. 严格, 特殊
|
||||
|
||||
#### **二、 单项选择题**
|
||||
|
||||
1. **B** (会先检查更高优先级的规则)
|
||||
2. **C** (score=85 满足 `>=60`,执行后跳出整个结构)
|
||||
3. **BC** (这是对 `if-else if-else` 完整性最准确的描述)
|
||||
4. **A** (`x > 3` 成立,输出"A";接着 `y < 5` 不成立,执行内层 `else`,输出"C")
|
||||
5. **A** (一旦第一个条件满足,就不会再检查后面的 `else if`)
|
||||
6. **B** (讲义优点部分明确指出:逻辑清晰,代码结构反映了分步解决的思考过程)
|
||||
7. **C** (这是对 `else if` 最核心的理解,体现了它的“否则,如果...”)
|
||||
8. **C** (`else` 后面不能也不需要带条件判断)
|
||||
9. **B** (外层分支的目的就是找出最大的数)
|
||||
10. **A** (`num=8`时,A选项的 `num<5` 和 `num<8` 都不满足,执行 `else`;B选项的 `num>8` 不满足,执行 `else`;C选项 `num==8` 满足,输出B;D选项都不满足,执行`else`)
|
||||
|
||||
#### **三、 判断题**
|
||||
1. **×** (一旦满足条件,就会跳出整个结构,不再检查后续分支)
|
||||
2. **√** (这是一个 `if-else if-else` 结构的语法规则)
|
||||
3. **×** (`if` 可以单独存在,`else` 和 `else if` 都是可选的)
|
||||
4. **√** (这就是条件嵌套的定义)
|
||||
5. **×** (顺序至关重要。如果交换,当输入12时,`if(x > 5)`会先被满足,逻辑就错了)
|
||||
6. **√** (讲义中明确指出了这两种解法的优缺点)
|
||||
7. **√** (这是两个独立的 `if` 语句,不是 `if-else if` 结构。两个条件都满足,所以都会执行)
|
||||
8. **√** (这是 `else if` 的核心逻辑)
|
||||
9. **√** (讲义中明确提到,嵌套解法反映了“分步解决”的思考过程)
|
||||
10. **×** (执行块内都可以嵌套,`if`, `else if`, `else` 的代码块内均可)
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
### **C++ `if` 的多分支与条件嵌套 课后习题**
|
||||
|
||||
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
|
||||
|
||||
#### **一、 填空题**
|
||||
|
||||
1. `if-else` 结构主要解决“**二选一**”的问题,而 `if-else if-else` 结构则解决了“**\_\__\_\_\_\_\_\_**”的问题。
|
||||
|
||||
2. `if-else if-else` 结构也被称为 **\_\_\_\__\_\_\_\_\_\_\_** 结构,它的核心特点是“择一执行”,即整个结构中最多只有 **\_\_\__\_\_\_\_\_\_\_\_** 个代码块会被执行。
|
||||
|
||||
3. 在 `if-else if-else` 结构中,`else` 关键字的作用是作为“**\_\_\__\_\_\_\_\_\_\_\_**”选项,当所有 `if` 和 `else if` 的条件都**\_\__\_\_\_\_\_\_\_\_\_** (填写“满足”或“不满足”)时,它的代码块才会被执行。
|
||||
|
||||
4. 将一个 `if` 语句完整地放入另一个 `if` 或 `else` 语句的执行代码块中,这种结构被称为 **\_\__\_\_\_\_\_\_\_\_\_\_\_\_\_**。
|
||||
|
||||
5. 在编写 `if-else if-else` 结构时,为了保证逻辑的正确性,通常应该将范围最**\_\_\_\_\_\_\__\_\_\_\_**、最**\_\__\_\_\_\_\_\_\_\_\_**的条件放在最前面。
|
||||
|
||||
#### **二、 单项选择题**
|
||||
|
||||
( ) 1. 根据课程和讲义中酒店保安的例子,如果来了一位“普通VIP”,保安的决策流程是怎样的?
|
||||
A. 直接跳到“普通VIP”规则,并带他去二层 B. 先判断他是不是顶级VIP,如果不是,再判断他是不是普通VIP
|
||||
C. 同时判断他是不是 顶级VIP 和 普通VIP D. 检查完所有规则后,才决定带他去二层
|
||||
|
||||
( ) 2. 观察以下代码片段,当 `int score = 85;` 时,程序的输出是什么?
|
||||
```cpp
|
||||
if (score >= 90) {
|
||||
cout << "优秀" << endl;
|
||||
} else if (score >= 60) {
|
||||
cout << "及格" << endl;
|
||||
} else {
|
||||
cout << "不及格" << endl;
|
||||
}
|
||||
```
|
||||
A. 优秀 B. 良好 C. 及格 D. 不及格
|
||||
|
||||
( ) 3. 关于 `if-else if-else` 结构的执行,以下说法正确的是?
|
||||
A. 只要有条件满足,所有代码块都会被执行 B. 至少有一个代码块会被执行
|
||||
C. 如果有 `else`,保证有且仅有一个代码块被执行 D. 可能会有多个 `else if` 的代码块被同时执行
|
||||
|
||||
( ) 4. 对于定义了变量 `int x = 5, y = 10;` 运行以下代码,输出结果是什么?
|
||||
```cpp
|
||||
if (x > 3) {
|
||||
cout << "A";
|
||||
if (y < 5) {
|
||||
cout << "B";
|
||||
} else {
|
||||
cout << "C";
|
||||
}
|
||||
} else {
|
||||
cout << "D";
|
||||
}
|
||||
```
|
||||
A. AC B. AB C. D D. A
|
||||
|
||||
( ) 5. 对于代码 `if (a > 10) { ... } else if (a > 5) { ... }`,如果变量 `a` 的值是 `12`,哪个代码块会被执行?
|
||||
A. `if (a > 10)` 对应的代码块 B. `else if (a > 5)` 对应的代码块
|
||||
C. 两个代码块都会被执行 D. 两个代码块都不会被执行
|
||||
|
||||
( ) 6. 在三数排序的案例中,相对于“纯粹的多分支判断”,“嵌套分支”解法的主要优点是?
|
||||
A. 代码行数更少 B. 逻辑更清晰,将复杂问题分步解决
|
||||
C. 运行效率更高 D. 使用的关键字更少
|
||||
|
||||
( ) 7. 从字面和逻辑上理解,`else if (表达式)` 的含义最准确的是?
|
||||
A. 并且,如果 表达式 成立 B. 或者,如果 表达式 成立
|
||||
C. 在前面的所有条件都不成立的前提下,如果 表达式 成立
|
||||
D. 无论如何,检查 表达式 是否成立
|
||||
|
||||
( ) 8. 关于 `if-else if-else` 结构中最后的 `else` 部分,下列哪个说法是**错误**的?
|
||||
A. 它是可选的,可以不写 B. 它用于处理所有 `if` 和 `else if` 条件都不满足的情况
|
||||
C. 它必须带一个条件判断,例如 `else (表达式)` D. 加上它可以让程序处理之前的所有条件都不满足的情况
|
||||
|
||||
( ) 9. 当我们比较三个数字的时候,当程序执行到 `if (a >= b && a >= c)` 的内部代码块时,如下的判断哪个是正确的?
|
||||
A. a 是三个数中最小的 B. a 是三个数中最大的
|
||||
C. a, b, c 三个数完全相等 D. b 和 c 的大小关系已经确定
|
||||
|
||||
( ) 10. 给定代码 `int num = 8;`,以下哪个 `if` 结构会输出 "C"?
|
||||
A. `if(num<5){cout<<"A";} else if(num<8){cout<<"B";} else{cout<<"C";}`
|
||||
B. `if(num>10){cout<<"A";} else if(num>8){cout<<"B";} else{cout<<"C";}`
|
||||
C. `if(num>9){cout<<"A";} else if(num==8){cout<<"B";} else{cout<<"C";}`
|
||||
D. `if(num<0){cout<<"A";} else if(num>10){cout<<"B";} else{cout<<"C";}`
|
||||
|
||||
#### **三、 判断题 (对的打“√”,错的打“×”)**
|
||||
( ) 1. 在一个 `if-else if-else` 结构中,如果第一个 `if` 的条件为真,程序会会继续检查后面的 `else if` 条件。
|
||||
|
||||
( ) 2. `if-else if-else` 结构中,`else if` 可以有很多个,但 `if` 和 `else` 最多只能有1个。
|
||||
|
||||
( ) 3. 一个 `if` 结构必须包含 `else` 部分,否则代码会编译失败。
|
||||
|
||||
( ) 4. 在 C++ 中,`if` 语句的执行块内可以再包含另一个完整的 `if-else` 结构。
|
||||
|
||||
( ) 5. 对于 `if (x > 10) { ... } else if (x > 5) { ... }` 这样的结构,条件 `x > 10` 和 `x > 5` 的顺序可以随意交换,不会影响程序的逻辑结果。
|
||||
|
||||
( ) 6. 三数排序案例中,解法一(纯粹使用多分支判断)的优点是逻辑简单,但缺点是存在重复判断。
|
||||
|
||||
( ) 7. 对于代码 `int num = 10; if (num > 5) { cout << "A"; } if (num > 8) { cout << "B"; }`,屏幕上会输出 "AB"。
|
||||
|
||||
( ) 8. `else if` 中的 `else` 关键字,其隐含了:在此之前的所有 `if` 和 `else if` 的条件判断结果均为 `false`。
|
||||
|
||||
( ) 9. 用嵌套分支解决三数排序问题,体现了“我们人类的分步解决”的思想,理解起来会更容易。
|
||||
|
||||
( ) 10. `if` 语句只能嵌套在另一个 `if` 语句的代码块中,不能嵌套在 `else` 的代码块中。
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
+157
@@ -0,0 +1,157 @@
|
||||
### **C++ `switch` 多选择语句 讲义**
|
||||
|
||||
#### **1. 引言**
|
||||
|
||||
* **问题引入:多分支选择的困境**
|
||||
|
||||
在之前的学习中,我们掌握了 `if-else if-else` 结构,它能帮助我们处理各种复杂的判断。例如,设计一个“自动贩猫机”,根据投入的金额,输出对应的猫咪:
|
||||
|
||||
```cpp
|
||||
if (n == 9) {
|
||||
cout << "小白";
|
||||
} else if (n == 8) {
|
||||
cout << "小黑";
|
||||
} else if (n == 6) {
|
||||
cout << "小棕";
|
||||
} else if (n == 4) {
|
||||
cout << "小灰";
|
||||
} else {
|
||||
cout << "无";
|
||||
}
|
||||
```
|
||||
这段代码功能正确,但当选项非常多时,一长串的 `else if` 会显得有些重复和臃肿。我们不禁会想:对于这种**只针对同一个变量进行等值判断**的场景,有没有更清晰、更结构化的写法呢?
|
||||
|
||||
* **解决方案:`switch` 语句**
|
||||
|
||||
答案是肯定的。C++ 为这类“多路等值选择”场景,提供了一个专门的解决方案——`switch` 语句。它能让我们的代码意图一目了然,极大地提高代码的可读性。
|
||||
|
||||
* **学习目标**:
|
||||
1. 理解 `switch` 语句与 `if-else if` 在逻辑上的核心区别。
|
||||
2. 掌握 `switch`, `case`, `break`, `default` 四个关键字的语法和作用。
|
||||
3. 深刻理解并规避 `switch` 语句最常见的陷阱——“case穿透”。
|
||||
4. 学会利用 `switch` 的特性合并相似逻辑,编写简洁高效的代码。
|
||||
|
||||
---
|
||||
|
||||
#### **2. 核心思想**
|
||||
|
||||
`if-else if` 和 `switch` 的工作方式有着本质的不同:
|
||||
|
||||
* **`if-else if` 的逻辑是“顺序比较”**:
|
||||
它像一个哨兵,拿着一个值,从第一个条件开始逐一盘问:“你是9吗?”、“你是8吗?”、“你是6吗?”... 直到找到匹配的条件或者走到最后的 `else`。这是一个**串行**的过程。
|
||||
|
||||
* **`switch` 的逻辑是“直接跳转”**:
|
||||
它更像一个“对号入座”系统。`switch` 会先看一下变量的值(比如是8),然后直接在内部的“情况列表 (`case`)”中找到值为8的标签,并**直接跳转**到该位置开始执行代码。这是一个**直接**的过程,在选项很多时通常效率更高。
|
||||
|
||||
---
|
||||
|
||||
#### **3. 语法详解 (构成与规则)**
|
||||
|
||||
我们来看一下 `switch` 语句的完整、规范的结构:
|
||||
|
||||
```cpp
|
||||
switch (表达式) {
|
||||
case 常量值1:
|
||||
// 当'表达式'的值等于'常量值1'时,执行此处的代码
|
||||
break;
|
||||
case 常量值2:
|
||||
// 当'表达式'的值等于'常量值2'时,执行此处的代码
|
||||
break;
|
||||
// ...可以有任意多个case...
|
||||
default:
|
||||
// 当'表达式'的值与上面所有case都不匹配时,执行此处的代码
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
* **关键字剖析**:
|
||||
* **`switch (表达式)`**: 这里的“表达式”是我们要判断的变量或计算结果,它的值必须是**整数类型**(如 `int`, `char`, `bool` 等)。
|
||||
* **`case 常量值:`**: 每个 `case` 都是一个“路牌”或“标签”。`case` 后面必须跟一个**常量**(如 `8`, `'A'`),不能是变量。程序会用 `switch` 表达式的值与这些常量值进行匹配。
|
||||
* **`break;`**: **这是 `switch` 语句的刹车**。当一个 `case` 的代码块执行完毕后,`break` 会立即终止并跳出整个 `switch` 结构。**如果缺少 `break`,将会引发“case穿透”**。
|
||||
* **`default:`**: 这是一个**可选**的“默认”或“其他”分支。如果表达式的值与所有 `case` 都不匹配,程序就会执行 `default` 下的代码块。它功能上类似于 `if-else if` 链条中最后的那个 `else`。
|
||||
|
||||
---
|
||||
|
||||
#### **4. 关键机制与技巧**
|
||||
|
||||
##### **陷阱:“Case穿透”**
|
||||
|
||||
让我们回到“贩猫机”的例子,如果我们在写 `switch` 时,忘记了写 `break`,会发生什么?
|
||||
|
||||
```cpp
|
||||
// 错误的示例 - 忘记写 break
|
||||
int n = 8;
|
||||
switch(n) {
|
||||
case 9:
|
||||
cout << "小白";
|
||||
case 8:
|
||||
cout << "小黑"; // 程序会从这里开始执行
|
||||
case 6:
|
||||
cout << "小棕";
|
||||
case 4:
|
||||
cout << "小灰";
|
||||
default:
|
||||
cout << "无";
|
||||
}
|
||||
// 最终输出: 小黑小棕小灰无
|
||||
```
|
||||
|
||||
* **执行分析**:
|
||||
1. `switch(n)` 发现 `n` 的值是 `8`。
|
||||
2. 程序直接**跳转**到 `case 8:` 标签处。
|
||||
3. 执行 `cout << "小黑";`。
|
||||
4. **由于 `case 8` 后面没有 `break`,程序不会停止!** 它会无视下面的 `case 6:`、`case 4:` 等标签,像一辆失控的汽车一样,继续向下执行所有代码,直到遇到一个 `break` 或者 `switch` 结构的末尾。
|
||||
5. 因此,它会接着执行 `cout << "小棕";`、`cout << "小灰";` 和 `cout << "无";`。
|
||||
|
||||
**结论**:忘记写 `break` 是 `switch` 语句中最常见的逻辑错误。**请养成写完一个 `case` 的逻辑后,立即补上 `break` 的好习惯。**
|
||||
|
||||
##### **合并相似分支:有意利用“穿透”**
|
||||
|
||||
虽然“穿透”通常是 Bug 的来源,但我们也可以巧妙地利用它来简化代码。当多个不同的 `case` 需要执行完全相同的操作时,我们可以将它们堆叠在一起。
|
||||
|
||||
* **案例**:判断输入的字母是元音还是辅音。
|
||||
|
||||
```cpp
|
||||
char letter = 'i';
|
||||
switch (letter) {
|
||||
// 对于 a, e, i, o, u 这五种情况,都执行相同的逻辑
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
cout << "是元音字母" << endl;
|
||||
break; // 执行完后跳出
|
||||
default:
|
||||
cout << "是辅音字母" << endl;
|
||||
break;
|
||||
}
|
||||
// 输出: 是元音字母
|
||||
```
|
||||
在这个例子中,当 `letter` 是 `i` 时,程序跳转到 `case 'i':`,因为前面没有任何 `break`,它会一直“穿透”下去,直到 `case 'u':` 之后,执行 `cout << "是元音字母" << endl;`,然后 `break`。这种写法清晰地表达了“对于这一组情况,执行相同的操作”的意图。
|
||||
|
||||
---
|
||||
|
||||
#### **5. 使用场景与限制 (`switch` 和 `if-else if`)**
|
||||
|
||||
`switch` 并非 `if-else if` 的完全替代品,它有自己的使用领域。
|
||||
|
||||
| 特性 | `switch` 语句 | `if-else if-else` 语句 |
|
||||
| :------------ | :----------------------------------------------- | :------------------------------------------------------ |
|
||||
| **比较类型** | 只能进行**等于 (==)** 的比较 | 可以进行任意逻辑条件的比较 (`>`, `<`, `!=`, `&&`, `||`) |
|
||||
| **判断变量** | 必须是**同一个**变量或表达式 | 每次判断的条件可以完全不同 |
|
||||
| **`case` 值** | 必须是**整型或字符型常量** | 条件中的值可以是变量,类型不限 |
|
||||
| **适用场景** | **等值判断(就是判断是否与某个值相等)** | **区间判断**、**复杂逻辑组合**、所有通用判断场景 |
|
||||
| **可读性** | 在处理多个等值选择时,结构更清晰,可读性**更高** | 分支过多或条件复杂时,可读性可能下降 |
|
||||
|
||||
**简单总结**:当你需要判断一个变量**等于**哪个**具体常量值**时,`switch` 是更优的选择。而在进行**范围判断**(如 `score > 90`)或**复合条件判断**时,必须使用 `if-else if`。
|
||||
|
||||
---
|
||||
|
||||
#### **6. 总结**
|
||||
|
||||
1. **功能定位**:`switch` 是处理**多路等值选择**的专用结构,比 `if-else if` 更清晰、高效。
|
||||
2. **`break` **:务必为每个独立的 `case` 分支添加 `break`,以防止意外的“case穿透”。
|
||||
3. **合并 `case`**:当多个情况执行相同逻辑时,可以利用“穿透”特性将它们分组,以简化代码。
|
||||
4. **`default` 保底**:总是提供一个 `default` 分支来处理所有未预料到的情况,这能让你的程序更加健壮。
|
||||
5. **明确限制**:记住 `switch` 只能用于整型/字符型变量的等值判断,不能用于范围和复杂逻辑。
|
||||
BIN
Binary file not shown.
+35
@@ -0,0 +1,35 @@
|
||||
### 参考答案
|
||||
|
||||
#### **一、 填空题**
|
||||
|
||||
1. 对号入座 (或 直接跳转)
|
||||
2. `case`
|
||||
3. `break`
|
||||
4. `default`
|
||||
5. case 穿透
|
||||
|
||||
#### **二、 单项选择题**
|
||||
|
||||
1. B
|
||||
2. B (从 `case 2` 开始穿透到 `case 3`,但 `case 3` 后面没有 `default`,到此为止)
|
||||
3. C
|
||||
4. C
|
||||
5. B
|
||||
6. C
|
||||
7. B
|
||||
8. C
|
||||
9. B (从 `case 'B'` 开始,穿透到 `case 'C'`,遇到 `break` 停止)
|
||||
10. B
|
||||
|
||||
#### **三、 判断题**
|
||||
|
||||
1. √
|
||||
2. × (`default` 分支是可选的)
|
||||
3. × (`case` 后面必须跟一个常量)
|
||||
4. √
|
||||
5. √
|
||||
6. × (`switch` 不能做范围判断,所以 `if` 更通用)
|
||||
7. √
|
||||
8. × (这是逻辑错误,不是编译错误,程序能正常运行但结果可能不符合预期)
|
||||
9. √
|
||||
10. √ (这被称为嵌套 `switch`,是合法的)
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
### C++ switch 多选择语句 课后习题
|
||||
|
||||
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
|
||||
|
||||
#### **一、 填空题**
|
||||
|
||||
1. `if-else if` 的逻辑是“顺序比较”,而 `switch` 的逻辑是“**\_\_\_\_\_\_\_\_\_\_\_\_\_**”,在选项多时效率更高。
|
||||
|
||||
2. `switch` 语句中,每个选项都由关键字 **\_\_\_\_\_\_\_\_\_\_\_\_\_** 开头,后面跟一个常量值和冒号。
|
||||
|
||||
3. 为了防止“case 穿透”,在每个独立的 `case` 代码块结束时,都应该加上 **\_\_\_\_\_\_\_\_\_\_\_\_\_** 语句。
|
||||
|
||||
4. 如果 `switch` 表达式的值与所有 `case` 都不匹配,程序会执行 **\_\_\_\_\_\_\_\_\_\_\_\_\_** 分支下的代码。
|
||||
|
||||
5. 一个 `case` 后面忘记写 `break`,程序会继续向下执行之后的所有代码,这种现象叫做“**\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_**”。
|
||||
|
||||
#### **二、 单项选择题**
|
||||
|
||||
( ) 1. 阅读代码,当输入为 `2` 时,输出结果是什么?
|
||||
```cpp
|
||||
int n;
|
||||
cin >> n;
|
||||
switch(n) {
|
||||
case 1: cout << "Apple"; break;
|
||||
case 2: cout << "Banana"; break;
|
||||
case 3: cout << "Cherry"; break;
|
||||
}
|
||||
```
|
||||
A. Apple B. Banana C. Cherry D. 没有输出
|
||||
|
||||
( ) 2. 阅读代码,当输入为 `2` 时,输出结果是什么? (注意:缺少 `break`)
|
||||
```cpp
|
||||
int n;
|
||||
cin >> n;
|
||||
switch(n) {
|
||||
case 1: cout << "A";
|
||||
case 2: cout << "B";
|
||||
case 3: cout << "C";
|
||||
}
|
||||
```
|
||||
A. B B. BC C. ABC D. C
|
||||
|
||||
( ) 3. 阅读代码,当输入为 `5` 时,输出结果是什么?
|
||||
```cpp
|
||||
int n;
|
||||
cin >> n;
|
||||
switch(n) {
|
||||
case 1: cout << "A"; break;
|
||||
case 2: cout << "B"; break;
|
||||
default: cout << "Other";
|
||||
}
|
||||
```
|
||||
A. A B. B C. Other D. 没有输出
|
||||
|
||||
( ) 4. `switch` 语句主要用来替代哪种结构的 `if` 语句?
|
||||
A. `if (score > 90)`
|
||||
B. `if (a > 0 && b > 0)`
|
||||
C. `if (day == 1) { ... } else if (day == 2) { ... } else if (day == 3) { ... }`
|
||||
D. `if (password != "123")`
|
||||
|
||||
( ) 5. 下列哪种判断**不能**直接用 `switch` 语句实现?
|
||||
A. 判断某天是周几 B. 判断成绩是否及格
|
||||
C. 判断输入的字符是不是 'Y' D. 判断用户的选择是不是 1
|
||||
|
||||
( ) 6. `switch (n)` 中,`n` 的结果**不能**是什么类型?
|
||||
A. `int` B. `char` C. `double` D. `bool`
|
||||
|
||||
( ) 7. 在 `switch` 结构中,`default` 关键字的作用是?
|
||||
A. 提供一个默认的变量值 B. 当所有 `case` 都不匹配时执行
|
||||
C. 必须写在 `switch` 的最开始 D. 用来结束 `switch` 语句
|
||||
|
||||
( ) 8. 为了判断一个字符 `c` 是不是元音字母(a, e, i, o, u),最高效的 `switch` 写法是?
|
||||
A. 为 a, e, i, o, u 分别写五个独立的 `case`,每个都带 `break`
|
||||
B. 使用 `if (c=='a' || c=='e' ...)`
|
||||
C. 将 `case 'a': case 'e': case 'i': case 'o': case 'u':` 堆叠在一起,共享一个代码块
|
||||
D. `switch` 无法实现此功能
|
||||
|
||||
( ) 9. 阅读代码,当输入为 `'B'` 时,输出结果是什么?
|
||||
```cpp
|
||||
char c;
|
||||
cin >> c;
|
||||
switch(c) {
|
||||
case 'A': cout << "Apple";
|
||||
case 'B': cout << "Banana";
|
||||
case 'C': cout << "Cherry"; break;
|
||||
case 'D': cout << "Durian";
|
||||
}
|
||||
```
|
||||
A. Banana B. BananaCherry C. BananaCherryDurian D. Cherry
|
||||
|
||||
( ) 10. `case` 标签后面跟的值必须是?
|
||||
A. 一个变量 B. 一个常量 C. 一个表达式 D. 一个函数
|
||||
|
||||
#### **三、 判断题 (对的打“√”,错的打“×”)**
|
||||
|
||||
( ) 1. `switch` 语句只能用于进行“等于”的判断。
|
||||
( ) 2. 在 `switch` 语句中,`default` 分支是必须存在的,不能省略。
|
||||
( ) 3. `case` 后面跟的可以是 `case x:`,其中 `x` 是一个 `int` 类型的变量。
|
||||
( ) 4. `break` 语句的作用是跳出当前的 `switch` 结构。
|
||||
( ) 5. 如果好几个 `case` 需要执行的操作完全一样,可以利用“case穿透”来简化代码。
|
||||
( ) 6. `if-else if` 语句能实现的功能,`switch` 语句也一定能实现。
|
||||
( ) 7. `switch` 语句中,各个 `case` 标签的顺序不影响最终的逻辑结果(假设都正确使用了 `break`)。
|
||||
( ) 8. 忘记在 `case` 中写 `break` 会导致编译错误(CE)。
|
||||
( ) 9. `switch` 的逻辑是“直接跳转”,而 `if-else if` 是“顺序比较”。
|
||||
( ) 10. 可以在一个 `switch` 结构中,放置另一个 `switch` 结构。
|
||||
BIN
Binary file not shown.
Reference in new issue
Block a user