C++ 循环语句`while`、`for` 与 `do…while`(六十七)
一、while
循环
语法与执行流程
while (condition) statement;
condition
- 任何可隐式转换为
bool
的表达式,或是“带初始化”的变量声明(C++17 起支持)。 - 每次迭代前都会重新求值;如果条件为假(
false
),循环一律终止,跳出到后续代码。
- 任何可隐式转换为
statement
- 通常是一条简单语句,也可以是一个【复合语句块(block)】
{ … }
。 - 如果需要多条语句共同构成循环体,务必用
{}
括起来,否则只有紧跟的第一条语句属于循环体。
- 通常是一条简单语句,也可以是一个【复合语句块(block)】
何时选用 while
- 无法预知迭代次数
- 读取标准输入直到 EOF:
std::vector<int> data; int x; while (std::cin >> x) // 读取失败(EOF 或格式错误)时结束data.push_back(x);
- 读取标准输入直到 EOF:
- 循环结束后仍需访问循环条件或控制变量
- 查找第一个负数元素,并在循环结束后检查是“找到”还是“遍历完毕”:
auto it = data.begin(); while (it != data.end() && *it >= 0)++it; if (it == data.end()) {// 没有负数 } else {// *it 是第一个负数 }
- 查找第一个负数元素,并在循环结束后检查是“找到”还是“遍历完毕”:
注意事项
- 避免“空循环体”陷阱
while (std::cin >> x && x != sentinel); // 空语句:循环体什么都不做,仅依赖条件部分“副作用”读入
- 防止漏写/多写分号
while (cond); // 错!分号会让循环体变成“空语句”,后面的代码将不受循环控制do_something(); // 永远只执行一次
- 循环变量作用域
- 在 C++17 及以后,你可以在
while
条件中声明变量:while (int n = getValue()) { // 每次迭代 n 都被创建并初始化// … 使用 n … } // 这里的 n 已超出作用域
- 在 C++17 及以后,你可以在
二、for
循环 快速概览
如果你对迭代次数大致有个概念,或者想把“初始化–条件–更新”三要素集中在一行,for
循环往往更简洁:
for (std::size_t i = 0; i < vec.size(); ++i) {process(vec[i]);
}
- 初始化语句(init-stmt):在循环开始前执行一次
- 条件表达式(cond):每次迭代前检查
- 更新表达式(increment):每次迭代后执行
- 循环体(statement):前面三部分控制何时进入、如何前进、何时退出
范围
for
(C++11)
当你只需遍历容器或数组时,推荐使用更简洁的for (auto &elem : container) {// … 使用 elem … }
三、do…while
循环
do…while
保证至少执行一次循环体,然后在末尾检查条件:
do {work();
} while (condition);
- 适用场景:需要先执行操作,再决定是否继续,例如:
- 菜单驱动程序:先显示菜单并读取一次用户选择,至少一次才有意义。
四、小结与实践指南
循环类型 | 检查条件时机 | 至少执行一次 | 常见用途 |
---|---|---|---|
while | 前 | 否 | 不确定次数、基于外部输入的循环 |
for | 前 | 否 | 已知次数或可整合 init/cond/incr 的常规迭代 |
do…while | 后 | 是 | 必须执行一次后再决定是否继续 |
- 规范花括号:即使循环体只有一行,也推荐使用
{ … }
,避免后期添加代码时引入“悬垂 else”或分号陷阱。 - 变量作用域:尽量将循环控制变量限制在最小作用域中——C++17 之后可在
while
或for
头部声明。 - 空循环:对“仅依赖条件副作用”的场景(如读取输入直至 EOF),可使用空语句;但要注释清晰,避免误删。
- 选择合适的循环:
- 以数据驱动(“有没有数据”)为主 →
while
- 以计数驱动(“执行 N 次”)为主 →
for
- 需要至少执行一次 →
do…while
- 以数据驱动(“有没有数据”)为主 →
掌握这三种循环及其差异,配合 范围 for
、算法库 和 标准容器,就能灵活、高效地应对绝大多数“重复执行”需求。希望这篇干货能帮助你在 C++ 项目中写出更清晰、健壮的循环代码!