Kodewick
第 6 课,共 30 课目录

if 和 switch

第 6 课,共 30 课 · 第 2 部分 · 流程和函数 · 约 15 分钟

到现在为止,程序都是从上到下每一行都跑。真正的程序要会做选择:分数够了显示「及格」,不够就不显示。这就是 if。

main.cpp
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,就会显示成单词:

main.cpp
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。两个代码块,正好跑其中一个:

main.cpp
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 一个接一个地问。从上往下,碰到第一个成立的条件,跑它的代码块,后面的就都不看了:

main.cpp
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}

并且、或者、不是

几个条件可以连起来:

写法意思什么时候是 true
a && b并且两个都成立
a || b或者至少一个成立
!a不是a 不成立
main.cpp
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 时,不会去做除法。

= 和 ==

= 是赋值,== 是比较。在条件里把 == 少写一个等号,程序照样能编译,只是意思全变了:

main.cpp
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 更清楚:

main.cpp
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 也跑了:

main.cpp
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 叠在一起:

main.cpp
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}
输出
很好

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

运费

订单金额 total 满 99 元免运费,否则运费 10 元。total 先是 85,后来改成 120:在两个空行处各写一个 if / else,显示两次运费。

要显示
运费:10
运费:0
exercise1.cpp
1#include <iostream>2 3int main() {4    int total = 85;5 6    total = 120;7 8    return 0;9}
输出
点「运行」或按 Ctrl+Enter
练习 2

能不能进场

年满 18 岁、并且有票的人才能进场。先来的人 age 是 20,has_ticket 是 false;后来的人 25 岁,有票。在两个空行处各判断一次:能进显示 请进,不能进显示 不能进场。

要显示
不能进场
请进
exercise2.cpp
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}
输出
点「运行」或按 Ctrl+Enter
练习 3

修好它:一路掉下去的 switch

level 是 2,本来只该显示 中等难度,现在却多显示了一行。改好它。

要显示
中等难度
exercise3.cpp
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}
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • 比较运算符 == != < > <= >= 得到 bool;cout 默认显示成 1 / 0,std::boolalpha 让它显示 true / false。
  • if / else if / else 从上往下问,只跑第一个成立的代码块;顺序很重要。
  • && 并且、|| 或者、! 不是;20 <= x <= 30 要写成两个比较。
  • 条件里把 == 写成 = 是赋值,能编译,但结果不对;g++ -Wall 会警告。
  • switch 拿一个整数或 char 和几个固定的值比;case 只决定从哪开始,break 才跳出去,default 接住剩下的。