if 和 switch
到现在为止,程序都是从上到下每一行都跑。真正的程序要会做选择:分数够了显示「及格」,不够就不显示。这就是 if。
1#include <iostream>2 3int main() {4 int score = 72;5 if (score >= 60) {6 std::cout << "及格\n";7 }8 std::cout << "分数:" << score << '\n';9 return 0;10}
及格 分数:72
if 后面的括号里是条件。条件成立,就跑花括号里的代码块;不成立,就跳过它。最后一行不在 if 里,总会运行。把 72 改成 45 再运行一次。
比较
条件通常是一个比较。C++ 有六个比较运算符:
| 写法 | 意思 |
|---|---|
a == b | 等于(两个等号) |
a != b | 不等于 |
a < b | 小于 |
a > b | 大于 |
a <= b | 小于或等于 |
a >= b | 大于或等于 |
比较的结果是一个 bool:true 或 false。用 cout 显示 bool,默认显示成 1 和 0;先送一个 std::boolalpha,就会显示成单词:
1#include <iostream>2 3int main() {4 int price = 25;5 bool cheap = price < 30;6 std::cout << cheap << '\n';7 std::cout << (price == 30) << '\n';8 std::cout << std::boolalpha << cheap << '\n';9 return 0;10}
1 0 true
注意第 7 行的括号:<< 比 == 先算,不加括号编译器会把它拆错。在 cout 里显示比较的结果,就把比较放在括号里。
std::string 也能用 == 和 < 比较(第 5 课讲过)。
if 和 else
条件不成立时也想做点什么,就加上 else。两个代码块,正好跑其中一个:
1#include <iostream>2 3int main() {4 int stock = 0;5 if (stock > 0) {6 std::cout << "有货,还剩 " << stock << " 件\n";7 } else {8 std::cout << "卖完了\n";9 }10 return 0;11}
卖完了
点单步,看看程序跳过了哪几行。
else if
不止两种情况时,用 else if 一个接一个地问。从上往下,碰到第一个成立的条件,跑它的代码块,后面的就都不看了:
1#include <iostream>2 3int main() {4 int score = 84;5 if (score >= 90) {6 std::cout << "优秀\n";7 } else if (score >= 75) {8 std::cout << "良好\n";9 } else if (score >= 60) {10 std::cout << "及格\n";11 } else {12 std::cout << "不及格\n";13 }14 return 0;15}
良好
84 也满足 score >= 60,但是 score >= 75 先成立了,所以只显示「良好」。顺序很重要:
这段程序显示什么?
1#include <iostream>2 3int main() {4 int score = 95;5 if (score >= 60) {6 std::cout << "及格\n";7 } else if (score >= 90) {8 std::cout << "优秀\n";9 }10 return 0;11}
从上往下问,第一个条件 score >= 60 就成立了,于是只跑它的代码块,后面的 else if 根本不看。范围大的条件放在前面,会把后面的挡住;要从严到宽地写。
并且、或者、不是
几个条件可以连起来:
| 写法 | 意思 | 什么时候是 true |
|---|---|---|
a && b | 并且 | 两个都成立 |
a || b | 或者 | 至少一个成立 |
!a | 不是 | a 不成立 |
1#include <iostream>2 3int main() {4 int temp = 26;5 bool raining = false;6 if (temp >= 20 && temp <= 30) {7 std::cout << "温度正好\n";8 }9 if (temp > 35 || raining) {10 std::cout << "待在家里\n";11 }12 if (!raining) {13 std::cout << "不用带伞\n";14 }15 return 0;16}
温度正好 不用带伞
20 <= temp <= 30 这种数学写法在 C++ 里不对:它先算 20 <= temp,得到 true 或 false,再拿这个结果和 30 比。要写成两个比较,用 && 连起来。
小技巧: && 左边已经不成立,右边就不再算了;|| 左边已经成立,右边也不算。所以可以写 count > 0 && total / count > 10:count 是 0 时,不会去做除法。
= 和 ==
= 是赋值,== 是比较。在条件里把 == 少写一个等号,程序照样能编译,只是意思全变了:
1#include <iostream>2 3int main() {4 int stock = 5;5 if (stock = 0) {6 std::cout << "卖完了\n";7 } else {8 std::cout << "还有 " << stock << " 件\n";9 }10 return 0;11}
还有 0 件
stock = 0 把 0 存进了 stock,整个式子的值就是 0,当成条件就是「不成立」。所以程序跑进了 else,还显示「还有 0 件」:stock 本来的 5 已经被改掉了。
编译器没有拦你:这是合法的 C++,它照样编译。这种 bug 只能靠自己留心。在自己的电脑上编译时,可以加上 -Wall 让 g++ 多给些警告,它就会提醒 suggest parentheses around assignment used as truth value(条件里用了赋值)。把 = 改成 == 再运行。
switch
拿一个整数(或 char)和好几个固定的值比,用 switch 更清楚:
1#include <iostream>2 3int main() {4 int day = 3;5 switch (day) {6 case 1:7 std::cout << "星期一\n";8 break;9 case 2:10 std::cout << "星期二\n";11 break;12 case 3:13 std::cout << "星期三\n";14 break;15 default:16 std::cout << "别的日子\n";17 }18 return 0;19}
星期三
switch 找到和 day 相等的那个 case,从那里开始跑,跑到 break 就跳出整个 switch。哪个 case 都不相等,就跑 default。case 后面只能写固定的值,不能写 day > 3 这样的条件,也不能写 std::string。
忘了 break
case 只决定从哪里开始。没有 break,程序会一直往下掉,把下面几个 case 也跑了:
1#include <iostream>2 3int main() {4 char size = 'M';5 switch (size) {6 case 'S':7 std::cout << "小杯\n";8 case 'M':9 std::cout << "中杯\n";10 case 'L':11 std::cout << "大杯\n";12 }13 return 0;14}
中杯 大杯
从 case 'M' 开始跑,可是没有 break,于是「大杯」也显示了。点单步看它怎么往下走。
有时候往下掉正是想要的:几个值做同一件事,就把 case 叠在一起:
1#include <iostream>2 3int main() {4 char grade = 'B';5 switch (grade) {6 case 'A':7 case 'B':8 std::cout << "很好\n";9 break;10 case 'C':11 std::cout << "还行\n";12 break;13 default:14 std::cout << "再加油\n";15 }16 return 0;17}
很好
练一练
写好代码,点检查。提示随便看,实在想不出来再看答案。
运费
✓订单金额 total 满 99 元免运费,否则运费 10 元。total 先是 85,后来改成 120:在两个空行处各写一个 if / else,显示两次运费。
运费:10 运费:0
1#include <iostream>2 3int main() {4 int total = 85;5 6 total = 120;7 8 return 0;9}
能不能进场
✓年满 18 岁、并且有票的人才能进场。先来的人 age 是 20,has_ticket 是 false;后来的人 25 岁,有票。在两个空行处各判断一次:能进显示 请进,不能进显示 不能进场。
不能进场 请进
1#include <iostream>2 3int main() {4 int age = 20;5 bool has_ticket = false;6 7 age = 25;8 has_ticket = true;9 10 return 0;11}
修好它:一路掉下去的 switch
✓level 是 2,本来只该显示 中等难度,现在却多显示了一行。改好它。
中等难度
1#include <iostream>2 3int main() {4 int level = 2;5 switch (level) {6 case 1:7 std::cout << "简单\n";8 case 2:9 std::cout << "中等难度\n";10 case 3:11 std::cout << "困难\n";12 }13 return 0;14}
这一课学会了
- 比较运算符
==!=<><=>=得到bool;cout默认显示成1/0,std::boolalpha让它显示true/false。 if/else if/else从上往下问,只跑第一个成立的代码块;顺序很重要。&&并且、||或者、!不是;20 <= x <= 30要写成两个比较。- 条件里把
==写成=是赋值,能编译,但结果不对;g++ -Wall会警告。 switch拿一个整数或char和几个固定的值比;case只决定从哪开始,break才跳出去,default接住剩下的。