C1-03 分支语句与比较运算符
比较运算符、if 语句与条件判断
学习目标:理解程序为什么需要“根据情况做选择”;掌握
<、<=、>、>=、==、!=六个比较运算符;学会使用if、if-else和if-else if-else;理解三目运算符的基本写法;能够完成“输入数据 → 判断条件 → 输出结果”的简单分支程序。
一、为什么需要分支
1. 第二课的程序有什么特点
第二课中的程序通常是一条路走到底:
int a, b;
cin >> a >> b;
cout << a + b << endl;
程序会按照从上到下的顺序执行每一条语句。这种结构叫作顺序结构。
2. 现实问题需要“看情况”
很多问题不能只做同一种处理,而是要先判断情况:
- 成绩大于等于 60 分,输出“及格”;否则输出“不及格”。
- 一个数大于 0,是正数;小于 0,是负数;等于 0,是零。
- 一个数除以 2 的余数是 0,是偶数;否则是奇数。
- 两个数中,输出较大的那个。
这些问题都需要程序根据条件选择不同的道路,这种结构叫作分支结构。
3. 分支程序的基本流程
本课会经常遇到下面的流程:
输入数据(Input) → 判断条件(Condition) → 选择分支(Branch) → 输出结果(Output)
例如,判断成绩是否及格:
输入 score → 判断 score >= 60 → 输出“及格”或“不及格”
4. 本课的学习范围
本课先学习一个条件的判断:
score >= 60
n % 2 == 0
a > b
多个条件同时成立、至少一个条件成立,以及条件取反,需要使用逻辑运算符 &&、||、!,放在后面的课程学习。
二、比较运算符
1. 比较运算符是什么
比较运算符用来比较两个值的大小,或者判断两个值是否相等。
比较的结果只有两种,这种结果叫作布尔值:
- 条件成立,结果是
true,表示“真”; - 条件不成立,结果是
false,表示“假”。
在 C++ 中,true 通常可以看作 1,false 通常可以看作 0。
2. 六个比较运算符
| 运算符 | 名称 | 含义 | 示例 | 示例结果 |
|---|---|---|---|---|
< |
小于运算符 | 左边小于右边 | 3 < 4 |
true |
<= |
小于等于运算符 | 左边小于或等于右边 | 4 <= 4 |
true |
> |
大于运算符 | 左边大于右边 | 3 > 4 |
false |
>= |
大于等于运算符 | 左边大于或等于右边 | 3 >= 4 |
false |
== |
等于运算符 | 判断两边是否相等 | 3 == 3 |
true |
!= |
不等于运算符 | 判断两边是否不相等 | 3 != 4 |
true |
建议按照“大小关系在前,相等关系在后”的顺序记忆:
小于:<
小于等于:<=
大于:>
大于等于:>=
等于:==
不等于:!=
在比较运算符内部,<、<=、>、>= 的优先级高于 ==、!=。所以以后看到多个比较符号时,可以先计算大小关系,再计算相等关系。
3. 比较结果可以直接输出
cout << (3 < 4) << endl; // 输出 1,表示 true
cout << (3 > 4) << endl; // 输出 0,表示 false
cout << (5 == 5) << endl; // 输出 1,表示 true
这里的括号是必须的。因为输出运算符 << 的优先级高于比较运算符,下面的写法:
cout << 3 < 4;
会被 C++ 按照下面的顺序理解:
(cout << 3) < 4;
程序会先执行输出,再拿输出流对象继续和 4 比较,通常会出现编译错误。正确写法必须把比较表达式括起来:
cout << (3 < 4) << endl;
同理,输出 ==、!=、<=、>= 的结果时,也必须加括号:
cout << (5 == 5) << endl;
cout << (5 != 4) << endl;
cout << (5 <= 6) << endl;
cout << (5 >= 4) << endl;
4. 最容易混淆的 = 和 ==
| 符号 | 名称 | 作用 | 示例 |
|---|---|---|---|
= |
赋值运算符 | 把右边的值放进左边的变量 | a = 5; |
== |
等于运算符 | 判断两边是否相等 | a == 5 |
int a = 5;
a = 0; // 把 0 放进 a,改变 a 的值
a == 0 // 判断 a 是否等于 0
重点记忆: 一个等号
=是“放进去”,两个等号==是“判断相等”。写判断条件时,判断相等一定使用两个等号。
5. 比较运算符的常见用法
score >= 60 // 成绩达到 60 分
age < 18 // 年龄小于 18
a > b // a 大于 b
n % 2 == 0 // n 是偶数
n % 2 != 0 // n 是奇数
a != 0 // a 不等于 0
判断奇数时,推荐使用 n % 2 != 0。这样即使输入负数,也能表示“不能被 2 整除”。
三、比较表达式的计算顺序
1. 先算算术,再做比较
算术运算符的优先级高于比较运算符。因此,下面的表达式会先计算 a + b,再判断它是否大于 c:
int a = 3, b = 4, c = 5;
cout << (a + b > c) << endl; // 先算 3+4,再判断 7>5,输出 1
cout << (a * b >= c) << endl; // 先算 3*4,再判断 12>=5,输出 1
为了让代码更容易读懂,比较复杂时建议主动加括号:
if ((a + b) > c) {
cout << "a+b 更大" << endl;
}
2. 比较运算符不能像数学那样连写
数学中可以写:
a < b < c
但 C++ 中不能这样写:
if (a < b < c) { // 错误:逻辑通常不是你想要的
cout << "a、b、c 递增" << endl;
}
C++ 会先计算 a < b,结果得到 0 或 1,然后再拿这个 0 或 1 与 c 比较,结果很容易出错。
本课阶段,如果需要分两次判断,可以先写成嵌套的 if:
if (a < b) {
if (b < c) {
cout << "a < b 且 b < c" << endl;
}
}
以后学习逻辑运算符 && 后,可以把多个条件写在一起。
四、if 单分支语句
1. 基本语法
if (条件) {
// 条件成立时执行的语句
}
这是一个单分支语句。执行过程:
- 先计算括号里的条件;
- 如果条件为真,执行花括号里的代码;
- 如果条件为假,跳过花括号里的代码。
2. if 的流程图
%%{init: {"themeVariables": {"edgeLabelBackground": "#FFFFFF"}}}%%
flowchart TD
Start([开始]) --> Cond{条件成立吗?}
Cond -->|true 真| Action1["执行 if 花括号内的语句"]
Cond -->|false 假| Action2["跳过 if 语句"]
Action1 --> Continue["继续执行后面的语句"]
Action2 --> Continue
Continue --> End([结束])
classDef condition fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
classDef action fill:#fff9c4,stroke:#fbc02d,stroke-width:1px;
class Cond condition;
class Action1,Action2,Continue action;
3. 示例:判断正数
int n;
cin >> n;
if (n > 0) {
cout << "正数" << endl;
}
输入 5,输出:
正数
输入 -3,条件 n > 0 不成立,程序不输出任何内容。
4. 示例:达到目标才输出
int score;
cin >> score;
if (score >= 60) {
cout << "及格" << endl;
}
只有成绩大于等于 60 时,程序才输出“及格”。
5. 花括号要不要写
如果 if 后面只有一条语句,花括号有时可以省略:
if (n > 0)
cout << "正数" << endl;
但是初学阶段建议一律写花括号。这样即使以后增加语句,也不容易出错:
if (n > 0) {
cout << "正数" << endl;
cout << "这个数大于 0" << endl;
}
看下面的危险写法:
if (n > 0)
cout << "正数" << endl;
cout << "判断结束" << endl; // 这行不在 if 内,会一直执行
代码的缩进不会改变程序的真正结构,花括号才会。
五、if-else 双分支语句
1. 基本语法
if (条件) {
// 条件成立时执行
} else {
// 条件不成立时执行
}
执行过程是二选一:
- 条件为真,执行
if分支; - 条件为假,执行
else分支; - 两个分支只会执行一个。
2. if-else 的流程图
%%{init: {"themeVariables": {"edgeLabelBackground": "#FFFFFF"}}}%%
flowchart TD
Start([开始]) --> Cond{条件成立吗?}
Cond -->|true 真| Action1["执行 if 花括号内的语句"]
Cond -->|false 假| Action2["执行 else 花括号内的语句"]
Action1 --> Continue["继续执行后面的语句"]
Action2 --> Continue
Continue --> End([结束])
classDef condition fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
classDef action fill:#fff9c4,stroke:#fbc02d,stroke-width:1px;
class Cond condition;
class Action1,Action2,Continue action;
3. 示例:判断及格与不及格
int score;
cin >> score;
if (score >= 60) {
cout << "及格" << endl;
} else {
cout << "不及格" << endl;
}
输入 80,输出:
及格
输入 50,输出:
不及格
4. 示例:判断奇数和偶数
int n;
cin >> n;
if (n % 2 == 0) {
cout << "偶数" << endl;
} else {
cout << "奇数" << endl;
}
这里的条件是 n % 2 == 0:
- 成立,说明余数为 0,是偶数;
- 不成立,说明不是偶数,是奇数。
5. 示例:输出两个数中较大的数
int a, b;
cin >> a >> b;
if (a >= b) {
cout << a << endl;
} else {
cout << b << endl;
}
这里使用 >= 而不是 >,当 a 和 b 相等时,输出 a 或 b 都可以。
6. 三目运算符:用一个表达式完成二选一
当程序只需要根据一个条件,在两个值中选择一个时,可以使用三目运算符(也叫条件运算符)。它的基本形式是:
条件 ? 条件成立时的值 : 条件不成立时的值
执行过程只有三步:
- 先判断
条件; - 如果条件成立,整个表达式的结果就是冒号左边的值;
- 如果条件不成立,整个表达式的结果就是冒号右边的值。
可以把它理解成“把一个简单的 if-else 压缩成一行”。例如,求两个数中的较大值:
int a, b;
cin >> a >> b;
int mx = (a > b) ? a : b;
cout << mx << endl;
上面的代码等价于:
int mx;
if (a > b) {
mx = a;
} else {
mx = b;
}
这里的 (a > b) 是条件;如果条件为真,选择 a;否则选择 b。括号不是语法上必须的,但可以让条件范围更清楚,初学时建议保留。
三目运算符也可以直接放在输出语句中:
int a, b;
cin >> a >> b;
cout << ((a > b) ? a : b) << endl;
关键理解: 三目运算符的结果是一个值,所以可以把它赋值给变量、放进输出语句,也可以参与后续计算。
7. 三目运算符的应用
(1)三个数求最大值
先用三目运算符求出 a 和 b 中较大的数,再与 c 比较:
int a, b, c;
cin >> a >> b >> c;
int mx = (a > b) ? a : b;
mx = (mx > c) ? mx : c;
cout << mx << endl;
也可以把两个三目运算符嵌套起来直接写出:
int a, b, c;
cin >> a >> b >> c;
int mx = (a > b)
? ((a > c) ? a : c)
: ((b > c) ? b : c);
cout << mx << endl;
不过嵌套写法层次较多,阅读难度更高。初学阶段更推荐“先求两个数的最大值,再和第三个数比较”的写法。
(2)三个数求最小值
求最小值时,只需要把比较方向改成 <:
int a, b, c;
cin >> a >> b >> c;
int mn = (a < b) ? a : b;
mn = (mn < c) ? mn : c;
cout << mn << endl;
(3)判断奇偶并输出文字
三目运算符两边不一定只能放数字,也可以放字符串:
int n;
cin >> n;
cout << ((n % 2 == 0) ? "偶数" : "奇数") << endl;
这段代码等价于:
if (n % 2 == 0) {
cout << "偶数" << endl;
} else {
cout << "奇数" << endl;
}
使用建议: 三目运算符适合表示简单、清楚的二选一。若两个分支中包含多条语句,或者条件判断层次较多,应继续使用
if-else,不要为了少写几行代码而强行嵌套三目运算符。
六、if-else if-else 多分支语句
1. 基本语法
if (条件1) {
// 条件1 成立
} else if (条件2) {
// 条件1 不成立,条件2 成立
} else if (条件3) {
// 条件1、2 都不成立,条件3 成立
} else {
// 以上条件都不成立
}
程序从上往下判断:
- 先判断条件 1;
- 条件 1 不成立,再判断条件 2;
- 一旦某个条件成立,执行对应分支;
- 执行完成后跳出整个分支结构,不再判断下面的条件;
- 如果所有条件都不成立,执行最后的
else。
2. if-else if-else 的流程图
%%{init: {"themeVariables": {"edgeLabelBackground": "#FFFFFF"}}}%%
flowchart TD
Start([开始]) --> Cond1{条件 1?}
Cond1 -->|true 真| Action1["执行分支 1"]
Cond1 -->|false 假| Cond2{条件 2?}
Cond2 -->|true 真| Action2["执行分支 2"]
Cond2 -->|false 假| Cond3{条件 3?}
Cond3 -->|true 真| Action3["执行分支 3"]
Cond3 -->|false 假| Action4["执行 else 分支"]
Action1 --> Continue["继续执行后面的语句"]
Action2 --> Continue
Action3 --> Continue
Action4 --> Continue
Continue --> End([结束])
classDef condition fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
classDef action fill:#fff9c4,stroke:#fbc02d,stroke-width:1px;
class Cond1,Cond2,Cond3 condition;
class Action1,Action2,Action3,Action4,Continue action;
如果有更多个 else if,流程也是一样:只要前面的条件不成立,程序就会继续从上到下判断后面的条件;一旦某个条件成立,就不会再判断后面的分支。
3. 示例:成绩等级
int score;
cin >> score;
if (score >= 90) {
cout << "优秀" << endl;
} else if (score >= 80) {
cout << "良好" << endl;
} else if (score >= 60) {
cout << "及格" << endl;
} else {
cout << "不及格" << endl;
}
输入 85 时:
score >= 90不成立;score >= 80成立;- 输出“良好”,后面的条件不再判断。
关键理解: 能走到
else if (score >= 80),说明前面的score >= 90已经不成立,所以这里不用再写score < 90。
4. 条件顺序很重要
下面的写法虽然语法正确,但顺序不合理:
if (score >= 60) {
cout << "及格或更高" << endl;
} else if (score >= 90) {
cout << "优秀" << endl; // 永远走不到
}
因为分数达到 90 时,也一定达到 60,程序已经在第一个分支结束了。
通常应该把范围较大的条件放后面,或者把要求更高的条件放在前面:
if (score >= 90) {
cout << "优秀" << endl;
} else if (score >= 60) {
cout << "及格" << endl;
} else {
cout << "不及格" << endl;
}
5. 示例:判断正数、负数和零
int n;
cin >> n;
if (n > 0) {
cout << "正数" << endl;
} else if (n < 0) {
cout << "负数" << endl;
} else {
cout << "零" << endl;
}
这里三个结果正好覆盖了整数的三种情况。
6. 最后的 else 可以省略
如果不需要处理“以上条件都不成立”的情况,最后的 else 可以省略:
int n;
cin >> n;
if (n > 0) {
cout << "正数" << endl;
} else if (n < 0) {
cout << "负数" << endl;
}
当 n == 0 时,程序什么都不输出。
七、多个分支的经典用法
1. 三个数求最大值:逐步更新
不使用逻辑运算符,也可以求三个数中的最大值:
int a, b, c;
cin >> a >> b >> c;
int mx = a; // 先假设 a 最大
if (b > mx) {
mx = b; // b 更大,就更新 mx
}
if (c > mx) {
mx = c; // c 更大,就更新 mx
}
cout << mx << endl;
这种方法的思路是:
先让 mx 代表 a
再让 b 和 mx 比较
最后让 c 和 mx 比较
2. 三个数从小到大排序:比较并交换
如果要把三个数从小到大输出,可以使用比较并交换:
int a, b, c;
cin >> a >> b >> c;
int t;
if (a > b) {
t = a;
a = b;
b = t;
}
if (b > c) {
t = b;
b = c;
c = t;
}
if (a > b) {
t = a;
a = b;
b = t;
}
cout << a << " " << b << " " << c << endl;
交换两个变量时,不能直接写:
a = b;
b = a; // 错误:a 原来的值已经丢失
要借助临时变量保存其中一个值:
int t = a;
a = b;
b = t;
八、常见错误与注意事项
1. 有编译器提示的错误
| 编号 | 错误 | 识别信息(关键特征) | 后果 | 改正 |
|---|---|---|---|---|
| E1 | 比较结果直接输出但没有加括号,如 cout << 3 < 4; |
常见 no match for 'operator<' 或 no match for 'operator==' |
<< 先执行,表达式被错误解析 |
输出比较结果时写成 cout << (3 < 4); |
| E2 | 比较运算符写成中文符号 | 常见 stray、expected primary-expression 等提示 |
编译器无法识别运算符 | 使用英文半角符号 |
| E3 | 花括号或圆括号没有配对 | 常见 expected '}'、expected ')' |
分支结构无法正确编译 | 检查 { } 和 ( ) 是否成对 |
2. 没有固定报错,但结果或逻辑不对
下面这些问题通常可以编译通过,编译器不一定会提醒,需要通过阅读代码和测试数据发现。
| 编号 | 错误 | 识别信息(关键特征) | 后果 | 改正 |
|---|---|---|---|---|
| E4 | 把 == 写成 = |
无固定报错;重点搜索条件中是否只有一个 = |
变成赋值,判断结果通常错误 | 判断相等使用 == |
| E5 | if 后面加分号,如 if (a > 0); |
无固定报错;看到 if (...) ; 就要警惕 |
条件后的语句可能脱离 if |
if 后直接写花括号 |
| E6 | else 后面加分号 |
无固定报错;看到 else ; 就要警惕 |
else 分支变成空语句 |
else 后直接写花括号 |
| E7 | 漏写花括号 | 无固定报错;观察缩进和实际控制范围是否一致 | 多条语句中只有第一条受 if 控制 |
初学阶段一律加花括号 |
| E8 | 把 else if 写成两个独立的 if |
无固定报错;检查多个判断是否应该“只执行一个” | 多个条件可能先后执行 | 多选一使用 else if |
| E9 | 条件方向写反,如把 > 写成 < |
无固定报错;用边界数据测试 | 输出结果相反 | 对照题意检查左右两边 |
| E10 | a < b < c 连写 |
无固定报错;代码中出现连续两个比较符号 | C++ 会分两次计算,逻辑错误 | 分步判断;后续学习 && 后再组合 |
| E11 | else if 顺序不合理 |
无固定报错;某个分支永远测试不到 | 后面的分支可能永远执行不到 | 把更严格的条件放前面 |
| E12 | 忘记处理相等情况 | 无固定报错;重点测试 a == b |
两个数相等时没有正确分支 | 根据题意选择 >=、<= 或补充相等判断 |
| E13 | 只测试一种数据 | 无固定报错;只测了一个普通样例 | 其他分支可能藏着错误 | 每个分支都要测试 |
| E14 | 忘记边界值 | 无固定报错;没有测试 59、60、61 或 -1、0、1 |
临界情况判断错误 | 测试边界前、边界、边界后三个值 |
if 后加分号的陷阱
错误写法:
int a;
cin >> a;
if (a > 0); {
cout << "正数" << endl;
}
if (a > 0); 中的分号是一条空语句,表示 if 已经结束。后面的花括号不属于 if,所以无论 a 是否大于 0,都会输出“正数”。
正确写法:
if (a > 0) {
cout << "正数" << endl;
}
口诀:
if、else后面不加分号,直接跟花括号。