C++ 控制流
控制流(control flow)是程序的"指挥棒"——决定代码按什么顺序执行。没有控制流的程序就是"从上到下一行行执行",有了控制流,程序就能"判断分支""重复干活"。这一章我们看 C++ 的三大控制流:分支(if/switch)、循环(for/while)、跳转(break/continue)。
一、if/else 条件判断
最基础的条件判断,根据条件的真假选择执行哪段代码:
#include <iostream>
using namespace std;
int main() {
int score = 75;
// 1. 单分支
if (score >= 60) {
cout << "及格" << endl;
}
// 2. 双分支
if (score >= 60) {
cout << "及格" << endl;
} else {
cout << "不及格" << endl;
}
// 3. 多分支(else if 链)
if (score >= 90) {
cout << "A" << endl;
} else if (score >= 80) {
cout << "B" << endl;
} else if (score >= 70) {
cout << "C" << endl;
} else if (score >= 60) {
cout << "D" << endl;
} else {
cout << "F" << endl;
}
// 输出: C
return 0;
}几个要点:
- 条件必须是 bool 或能转 bool 的表达式:整数 0 是 false,非 0 都是 true。
- else if 不是关键字:它是 else 后跟一个 if 语句的简写,本质是嵌套。
- 花括号建议总是写:即便只有一条语句。Google C++ 风格指南强制要求,可以避免"苹果 goto bug"那种著名漏洞。
- 条件里声明变量(C++17):
if (int x = compute(); x > 0),变量在 if 作用域内有效。
二、switch 多分支
当需要根据一个变量的多个值做不同处理时,switch 比 if/else 链更清晰:
#include <iostream>
using namespace std;
int main() {
int day = 3;
// switch:根据一个整型/字符/枚举值跳转
switch (day) {
case 1:
cout << "周一" << endl;
break; // 必须 break,否则会"贯穿"执行下一个 case
case 2:
cout << "周二" << endl;
break;
case 3:
cout << "周三" << endl;
break;
case 4:
case 5:
cout << "周四周五" << endl; // 多个 case 共享一段代码
break;
default: // 默认分支
cout << "周末" << endl;
}
// 输出: 周三
// switch vs if/else:switch 适合"值匹配",if 适合"范围判断"
return 0;
}switch 的贯穿陷阱:case 后必须写 break,否则会"贯穿"执行下一个 case 的代码:
#include <iostream>
using namespace std;
int main() {
int level = 1;
// 不写 break 会"贯穿"(fallthrough)
switch (level) {
case 3:
cout << "High" << endl;
// 没有 break,继续执行 case 2!
case 2:
cout << "Mid" << endl;
// 没有 break,继续执行 case 1!
case 1:
cout << "Low" << endl;
break;
}
// level=1 时只输出: Low
// level=2 时输出: Mid Low
// level=3 时输出: High Mid Low
// 这种"贯穿"有时是故意的(共享代码),但容易出错
// 建议开 -Wimplicit-fallthrough 让编译器警告意外的贯穿
return 0;
}switch 的限制:
- 只能匹配整型/字符/枚举:不能匹配字符串、浮点(C++ 没这能力,Java 才有)。
- case 必须是编译期常量:不能写
case x:(x 是变量)。 - 适合"值匹配":多个离散值用 switch;范围判断用 if/else。
三、for 循环
for 循环用于"明确次数"的重复:
#include <iostream>
using namespace std;
int main() {
// 1. 经典 for 循环:初始化; 条件; 更新
for (int i = 0; i < 5; i++) {
cout << i << " ";
}
cout << endl;
// 输出: 0 1 2 3 4
// 2. 倒序
for (int i = 5; i > 0; i--) {
cout << i << " ";
}
cout << endl;
// 输出: 5 4 3 2 1
// 3. 步长为 2
for (int i = 0; i < 10; i += 2) {
cout << i << " ";
}
cout << endl;
// 输出: 0 2 4 6 8
// 4. 嵌套循环(经典:九九乘法表)
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= i; j++) {
cout << j << "*" << i << "=" << i*j << " ";
}
cout << endl;
}
return 0;
}三个组成部分:
- 初始化(
int i = 0):循环开始前执行一次。 - 条件(
i < 5):每次循环开始判断,为假就结束。 - 更新(
i++):每次循环体执行完后跑。
三个部分都可以省略,但分号要保留——for(;;) 就是死循环。
四、while 与 do-while
while 用于"次数不确定,只看条件"的循环:
#include <iostream>
using namespace std;
int main() {
// 1. while:先判断再执行
int i = 0;
while (i < 5) {
cout << i << " ";
i++;
}
cout << endl;
// 输出: 0 1 2 3 4
// 2. do-while:先执行一次再判断(至少跑一次)
int j = 10;
do {
cout << j << " ";
j++;
} while (j < 5);
cout << endl;
// 输出: 10 (即便条件一开始就为假,也执行一次)
// 3. while 实战:数字位数统计
int n = 12345;
int digits = 0;
while (n > 0) {
digits++;
n /= 10;
}
cout << "位数: " << digits << endl; // 5
return 0;
}- while:先判断再执行。条件一开始就为假就一次都不跑。
- do-while:先执行一次再判断。至少跑一次。用于"先做一遍再说"的场景,如菜单交互。
五、break 与 continue
这两个是循环里的"提前退出"机制:
#include <iostream>
using namespace std;
int main() {
// break:跳出整个循环
for (int i = 0; i < 10; i++) {
if (i == 5) break; // i=5 时跳出
cout << i << " ";
}
cout << endl;
// 输出: 0 1 2 3 4
// continue:跳过本次,进入下一次
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) continue; // 跳过偶数
cout << i << " ";
}
cout << endl;
// 输出: 1 3 5 7 9
// break 跳出嵌套循环:只能跳一层
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) break; // 只跳出内层 j 循环
cout << i << "," << j << " ";
}
}
cout << endl;
// 输出: 0,0 0,1 0,2 1,0 2,0 2,1 2,2
// 想一次跳多层:用 flag 或 goto
bool found = false;
for (int i = 0; i < 3 && !found; i++) {
for (int j = 0; j < 3 && !found; j++) {
if (i == 1 && j == 1) {
found = true; // 外层也会终止
}
}
}
return 0;
}- break:立刻跳出整个循环。
- continue:跳过本次循环体的剩余部分,进入下一次。
- 嵌套循环:break 只跳一层。要跳多层得用 flag 变量,或者把内层循环抽成函数配合 return。
六、range-for(C++11 必备)
这是现代 C++ 最常用的循环——遍历容器:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// C++11 引入的 range-for(类似 Python 的 for x in xs)
vector<int> nums = {1, 2, 3, 4, 5};
// 1. 只读访问
for (int x : nums) {
cout << x << " ";
}
cout << endl;
// 输出: 1 2 3 4 5
// 2. 用引用修改元素
for (int& x : nums) { // 注意 & 表示引用
x *= 2; // 修改原始元素
}
for (int x : nums) cout << x << " ";
cout << endl;
// 输出: 2 4 6 8 10
// 3. 用 auto 让编译器推导类型
for (auto& x : nums) {
x += 1;
}
// 4. 遍历字符串
string s = "hello";
for (char c : s) {
cout << c << "-";
}
cout << endl;
// 输出: h-e-l-l-o-
return 0;
}- 只读:
for (int x : nums)—— x 是元素的副本。 - 修改:
for (int& x : nums)—— x 是元素的引用,可以改原元素。 - auto:
for (auto& x : nums)—— 让编译器推导类型,最省心。 - 性能:遍历大对象时务必用引用,否则每个元素都会被拷贝一次,性能差几个数量级。
七、死循环与 goto
有些场景需要"无限循环 + 条件退出":
#include <iostream>
using namespace std;
int main() {
// 1. for(;;) 是经典死循环写法
int count = 0;
for (;;) {
count++;
if (count >= 10) break; // 必须有出口
}
// 2. while(true) 等价
int i = 0;
while (true) {
i++;
if (i >= 10) break;
}
// 死循环常用于:游戏主循环、服务监听、CLI 交互
// 但必须有明确的退出条件(break / return),否则会卡死
// 3. goto(了解,不要用)
// C++ 保留了 goto,可以无条件跳转
int x = 0;
loop:
x++;
if (x < 5) goto loop;
cout << x << endl; // 5
// 现代 C++ 强烈反对 goto,它会让代码"面条化"
return 0;
}- 死循环:游戏主循环、服务器监听、CLI 交互。必须有退出条件(break/return),否则卡死。
- goto:C++ 保留了,但不要用。它让代码"面条化",极难维护。唯一可以接受的是跳出多层嵌套循环,但用 flag 或抽函数更好。
小结
这一章你掌握了 C++ 的全部控制流:if/else 条件分支、switch 多分支(注意 break)、for 经典循环、while/do-while 条件循环、break/continue 跳转、range-for 现代遍历。下一篇我们看函数——怎么把代码组织成可复用的块。
← 上一篇 C++ 运算符
下一篇 C++ 函数 →