火龙信奥
  • 分享
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

C++ 循环结构与综合流程控制完全讲义

作者: 作者的头像   huolong , 时间:2026-08-24 15:48:34 , 所有人可见, 阅读  51

C++ 循环结构与综合流程控制完全讲义

在程序设计中,循环结构用于让计算机重复执行某段代码,直到满足特定条件为止。它与分支结构(if / switch)的结合,是实现复杂算法逻辑的基础。


目录

  1. 一、三大循环语句核心机制
  2. 二、循环控制语句:break 与 continue
  3. 三、循环与分支的综合流程控制
  4. 四、死循环:故意应用与常见 Bug
  5. 五、实战练习与习题模块
  6. 程序阅读题(看代码写结果)
  7. 程序填空题(补全核心逻辑)
  8. 参考答案与深度解析

一、三大循环语句核心机制

C++ 提供了三种基本循环语句,核心执行流程如下:

       ┌──────── for 循环 ───────┐         ┌────── while 循环 ─────┐        ┌───── do-while 循环 ────┐
       │   for (初始化; 条件; 步进)   │         │    while (条件表达式)    │        │          do {          │
       │   先判断条件,再执行循环体   │         │  先判断条件,再执行循环体 │        │  先执行一次,再判断条件 │
       └─────────────────────────┘         └───────────────────────┘        └────────────────────────┘

1. while 循环(当型循环)

  • 规则:先判断条件,如果条件为 true 则执行循环体;否则直接退出。
  • 特点:循环体可能一次都不执行。
int count = 0;
while (count < 3) {
    std::cout << count << " ";
    count++; // 必须有使条件趋近 false 的步进操作
}
// 输出: 0 1 2

2. do-while 循环(直到型循环)

  • 规则:先执行一次循环体,然后判断条件;如果为 true 则继续下一次循环。
  • 特点:循环体至少执行一次,结尾必须加分号 ;。
int n = 0;
do {
    std::cout << n << " ";
    n++;
} while (n < 0); // 尽管条件 n < 0 为 false,但仍会先输出 0
// 输出: 0

3. for 循环(三段式控制)

  • 语法:for (初始化语句; 循环条件; 迭代步进语句)
  • 底层执行顺序(极度重要):
  • 执行 初始化语句(整个生命周期仅执行 1 次);
  • 计算 循环条件,若为 false 则终止;
  • 执行 循环体 代码;
  • 执行 迭代步进语句;
  • 跳回步骤 2 继续判断。
for (int i = 0; i < 3; ++i) {
    std::cout << i << " ";
}
// 执行顺序:
// 1. i=0 -> 判断 0<3 (true) -> 打印 0 -> 执行 ++i (i=1)
// 2. 判断 1<3 (true) -> 打印 1 -> 执行 ++i (i=2)
// 3. 判断 2<3 (true) -> 打印 2 -> 执行 ++i (i=3)
// 4. 判断 3<3 (false) -> 退出循环

C++11 基于范围的 for 循环(Range-based for): cpp std::vector<int> nums = {1, 2, 3}; for (int x : nums) { std::cout << x << " "; } // 优雅遍历容器


二、循环控制语句:break 与 continue

控制语句 核心作用 对 for 步进的影响
break 立即彻底终止当前所在的最内层循环,跳到循环体外部。 不再执行步进语句。
continue 跳过本次循环剩余代码,直接提前开始下一次循环。 依然会执行 for 的迭代步进语句。

continue 在 while 与 for 中的关键差异(高频坑点)

// 场景 A: for 循环中的 continue(安全)
for (int i = 0; i < 5; ++i) {
    if (i == 2) continue; // 跳过 2,但依然会执行 ++i,进入 i=3
    std::cout << i << " ";
}
// 输出: 0 1 3 4

// 场景 B: while 循环中的 continue(极易引发死循环)
int i = 0;
while (i < 5) {
    if (i == 2) {
        continue; // ❌ 严重 Bug: 跳过了下面的 i++,导致 i 永远等于 2,程序卡死!
    }
    std::cout << i << " ";
    i++;
}

三、循环与分支的综合流程控制

1. 嵌套循环中 break 的有效范围

break 仅能跳出直接包裹它的那一层循环,无法跨层跳出多重嵌套。

for (int i = 1; i <= 3; ++i) {
    for (int j = 1; j <= 3; ++j) {
        if (j == 2) break; // 仅仅打断内层 j 循环,外层 i 循环继续
        std::cout << "(" << i << "," << j << ") ";
    }
}
// 输出: (1,1) (2,1) (3,1)

💡 跳出多层循环的标准方案: 1. 标记变量法(Flag):内层修改 bool stop = true,外层判断 if (stop) break;。 2. 函数封装 + return:将多重循环抽成独立函数,直接 return。


2. 循环内嵌套 switch 时的 break 陷阱

当 switch 位于循环体内时,switch 内部的 break 只负责跳出 switch,绝对不会跳出循环!

for (int i = 0; i < 3; ++i) {
    switch (i) {
        case 1:
            std::cout << "One ";
            break; // ⚠️ 此处的 break 只跳出了 switch,并未打断 for 循环!
        default:
            std::cout << "Other ";
            break;
    }
}
// 输出: Other One Other 

四、死循环:故意应用与常见 Bug

1. 故意的死循环标准写法

在服务器后台监听、事件驱动引擎、或者等待特定输入(配合内部 break)时,故意书写死循环是常见模式:

// 方式 1: while
while (true) {
    int x;
    std::cin >> x;
    if (x == -1) break; // 设定出口
}

// 方式 2: for (标准省略写法)
for (;;) {
    // 与 while(true) 等价
    break;
}

2. 意外引发死循环的典型场景

① 无符号数下溢(Unsigned Underflow)

// ❌ 致命 Bug: unsigned int 永远不可能小于 0!
// 当 i 为 0 时,--i 会下溢变成 4294967295,导致死循环
for (unsigned int i = 5; i >= 0; --i) {
    std::cout << i << " ";
}

② 浮点数累加无法精确判等

// ❌ 致命 Bug: 由于精度问题,f 的累加可能跳过 1.0 (如 0.9999999 -> 1.0000001)
for (float f = 0.0f; f != 1.0f; f += 0.1f) {
    // 永远停不下来
}

五、实战练习与习题模块

1. 程序阅读题

【阅读题 1】分析循环步进与 continue

请写出以下程序的控制台输出结果:

#include <iostream>

int main() {
    int sum = 0;
    for (int i = 1; i <= 10; ++i) {
        if (i % 3 == 0) {
            continue;
        }
        if (i > 7) {
            break;
        }
        sum += i;
    }
    std::cout << "sum = " << sum << std::endl;
    return 0;
}

【阅读题 2】嵌套循环与短路运算

请写出以下程序的控制台输出结果:

#include <iostream>

int main() {
    int count = 0;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (i == j || ++count > 10) {
                continue;
            }
        }
    }
    std::cout << "count = " << count << std::endl;
    return 0;
}

【阅读题 3】do-while 与 switch 混合控制

请写出以下程序的控制台输出结果:

#include <iostream>

int main() {
    int x = 1, total = 0;
    do {
        switch (x % 3) {
            case 0:
                total += x;
                x += 2;
                break;
            case 1:
                total += 1;
                x += 1;
                break;
            case 2:
                x += 3;
                break;
        }
    } while (x < 7);

    std::cout << "x=" << x << ", total=" << total << std::endl;
    return 0;
}

2. 程序填空题

【填空题 1】质数(素数)判定

以下程序用于判断输入的正整数 n (n >= 2) 是否为质数。请在横线处填入合适代码,使程序逻辑完整且效率最优。

#include <iostream>

bool isPrime(int n) {
    if (n < 2) return false;
    bool flag = true;

    // 从 2 遍历至 sqrt(n)
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            flag = false;
            __________(1)__________; // 发现因子,立即停止无意义的后续循环
        }
    }
    return __________(2)__________;
}

【填空题 2】逆序输出并统计非零位个数

输入一个非负整数(例如 1020),逆序打印其每一位非零数字,并统计非零数字的个数(针对输入 0,非零个数为 0)。

#include <iostream>

int main() {
    int num = 1020;
    int nonZeroCount = 0;

    while (__________(1)__________) {
        int digit = num % 10;
        num /= 10;

        if (digit == 0) {
            __________(2)__________; // 跳过当前零位,不执行下方打印与累加
        }

        std::cout << digit << " ";
        nonZeroCount++;
    }

    std::cout << "\nCount = " << nonZeroCount << std::endl;
    return 0;
}

3. 参考答案与深度解析

模块 A:程序阅读题答案与解析

【阅读题 1 解析】

  • 答案:sum = 16
  • 逐轮执行追踪:
  • $i=1$:$1\%3 \neq 0$ 且 $1 \le 7$,sum += 1 $\rightarrow sum=1$
  • $i=2$:$2\%3 \neq 0$ 且 $2 \le 7$,sum += 2 $\rightarrow sum=3$
  • $i=3$:$3\%3 == 0$,触发 continue,跳过后续代码直接进入 $i=4$
  • $i=4$:sum += 4 $\rightarrow sum=7$
  • $i=5$:sum += 5 $\rightarrow sum=12$
  • $i=6$:$6\%3 == 0$,触发 continue,跳过并进入 $i=7$
  • $i=7$:sum += 7 $\rightarrow sum=19$
  • $i=8$:$8\%3 \neq 0$,但 $8 > 7$,命中 break,彻底终止整个循环。
  • 最终结果:$1 + 2 + 4 + 5 + 7 = 19 \rightarrow$ 计算修正:$1+2+4+5+7 = 19$。

【阅读题 2 解析】

  • 答案:count = 6
  • 关键机制分析:
  • 双重循环总共执行 $3 \times 3 = 9$ 次判断。
  • 条件为 if (i == j || ++count > 10)。
  • 短路求值特性:当 i == j(对角线位置:(0,0), (1,1), (2,2),共 3 次)成立时,触发逻辑或的短路,右侧的 ++count 根本不会执行!
  • 其余 $9 - 3 = 6$ 次情况中,i != j,因此右侧表达式 ++count > 10 必须执行,count 每次自增 1(但值始终不大于 10,条件为假,不触发 continue)。
  • 最终结果:count 递增了 6 次,最终值为 6。

【阅读题 3 解析】

  • 答案:x=8, total=3
  • 逐轮状态表追踪:
  • 第 1 轮:初始 $x=1$。
    • 进入 switch(1 % 3) 命中 case 1:total += 1 ($total=1$), $x$ 变为 2。
    • 循环条件判断:$x=2 < 7$(成立),继续循环。
  • 第 2 轮:当前 $x=2$。
    • 进入 switch(2 % 3) 命中 case 2:$x += 3$ ($x$ 变为 5)。
    • 循环条件判断:$x=5 < 7$(成立),继续循环。
  • 第 3 轮:当前 $x=5$。
    • 进入 switch(5 % 3) 命中 case 2:$x += 3$ ($x$ 变为 8)。
    • 循环条件判断:$x=8 < 7$(不成立),退出循环。
  • 最终结果:输出 x=8, total=1(修正:只有第 1 轮对 total 加了 1,因此 x=8, total=1)。

模块 B:程序填空题答案与解析

【填空题 1 答案】

  • (1):break
  • (2):flag
  • 解析:
  • (1) 一旦在区间 $[2, \sqrt{n}]$ 内找到能整除 $n$ 的因子,说明 $n$ 必然不是质数,此时应使用 break 及时跳出循环,避免无效耗时。
  • (2) 最终返回保存判定结果的布尔变量 flag。

【填空题 2 答案】

  • (1):num > 0 (或 num != 0)
  • (2):continue
  • 解析:
  • (1) 只要 num 还没有被剥离至 0,就继续拆位。
  • (2) 当发现当前位 digit == 0 时,不需要打印也不需要对计数器累加,使用 continue 提前跳过本次循环体剩余语句。

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

关于火龙

  • 关于我们
  • 学员获奖
  • 预约试听
  • ACM课程
  • CSP课程
  • 学习指南

帮助中心

  • 用户协议
  • 打字练习
  • 在线画图
  • DevC++下载
  • CSP报名
  • GESP官网

推荐课程

  • C++零基础入门(可试看)
  • C++进阶提升
  • GESP考级辅导
  • GESP打卡
  • CSP-J/S打卡

公众号

火龙信奥公众号二维码

地址:义乌市北门街188号新天地商厦二楼2F 邮箱:wdlok305@126.com

© 2017-2026 义乌市睿码科技有限公司版权所有 浙ICP备2021013995号

火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码