第二节循环结构 ——while、do-while 和 for上一节我们学习了分支结构 —— 程序会 思考 了能根据条件做选择。但如果我想让程序重复做一件事呢比如打印 100 遍 我爱编程计算 1 加到 100 的和输出九九乘法表如果没有循环你就得写 100 遍、甚至更多遍相同的代码 —— 这也太蠢了。这时候就需要循环结构了。循环就是让程序重复执行一段代码直到满足某个条件才停止。C 语言提供了三种循环语句while循环先判断后执行适合不知道循环次数的场景do-while循环先执行后判断至少执行一次for循环最灵活、最常用适合知道循环次数的场景本节我们就把这三种循环一网打尽再加上break、continue和循环嵌套让你彻底掌握循环准备好了吗Lets go一、什么是循环结构循环结构就是根据条件重复执行一段代码叫循环体。就像跑步条件还没跑够 3 圈循环体继续跑每跑一圈检查一次直到跑够了就停下来┌───────────────┐ ↓ │ 判断条件 │ │ │ 为真 → 执行循环体 ─┘ 为假 → 结束循环循环有三个关键要素初始值循环从哪里开始条件判断什么时候结束更新每次循环后改变什么让条件最终能变成假少了任何一个都可能出问题比如死循环。二、while 循环while是最简单的循环也是最基础的。2.1 基本语法while (条件) { // 循环体条件为真时重复执行这里的代码 }执行流程先判断括号里的条件如果条件为真就执行循环体执行完循环体回到第 1 步再判断条件如果条件为假就结束循环继续往下执行特点先判断后执行。如果一开始条件就是假的循环体一次都不执行。2.2 第一个例子打印 1 到 5#include stdio.h int main() { int i 1; // ① 初始值从1开始 while (i 5) // ② 条件小于等于5就继续 { printf(%d , i); i; // ③ 更新每次加1否则永远是1死循环 } printf(\n循环结束\n); return 0; }运行结果1 2 3 4 5 循环结束我们来一步步看第 1 次i115 为真 → 打印 1i 变成 2第 2 次i225 为真 → 打印 2i 变成 3第 3 次i335 为真 → 打印 3i 变成 4第 4 次i445 为真 → 打印 4i 变成 5第 5 次i555 为真 → 打印 5i 变成 6第 6 次i665 为假 → 结束循环完美正好执行 5 次。2.3 再看一个例子计算 1 加到 100 的和#include stdio.h int main() { int i 1; // 循环变量从1开始 int sum 0; // 累加器初始为0 while (i 100) { sum sum i; // 把i加到sum里 i; // i加1 } printf(12...100 %d\n, sum); return 0; }运行结果12...100 5050经典的高斯求和问题用循环几行代码就搞定了。2.4 死循环⚠️新手必踩坑死循环如果循环条件永远为真循环就永远停不下来这叫死循环。while (1) { printf(停不下来啦\n); }或者更隐蔽的int i 1; while (i 5) { printf(%d\n, i); // 忘了写 ii永远是1条件永远为真 }死循环会让程序一直跑直到你强制关掉它。写循环的时候一定要检查循环变量有没有更新条件会不会最终变成假小技巧写 while 循环的时候建议按 初始值→条件→更新 三步走先把这三个要素都想清楚再写代码能有效避免死循环。三、do-while 循环do-while是while的变体区别是先执行后判断。3.1 基本语法do { // 循环体先执行一次 } while (条件); // 注意这里有个分号执行流程先执行一次循环体再判断条件如果条件为真继续循环如果条件为假结束循环特点先执行后判断。循环体至少执行一次。3.2 和 while 的对比来看一个直观的对比while 循环先判断int i 10; while (i 5) // 一开始就是假 { printf(%d\n, i); i; } // 一次都不执行什么也不输出do-while 循环先执行int i 10; do { printf(%d\n, i); // 先执行一次 i; } while (i 5); // 再判断是假的结束 // 输出10看到区别了吗即使条件一开始就是假的do-while也会执行一次循环体。3.3 do-while 的适用场景do-while用得比while少但在某些场景下特别合适比如菜单程序#include stdio.h int main() { int choice; do { // 先显示菜单 printf( 菜单 \n); printf(1. 开始游戏\n); printf(2. 设置\n); printf(3. 退出\n); printf(请选择); scanf(%d, choice); // 根据选择做不同的事 switch (choice) { case 1: printf(游戏开始\n); break; case 2: printf(进入设置\n); break; case 3: printf(再见\n); break; default: printf(输入错误请重新选择\n); break; } } while (choice ! 3); // 选3就退出 return 0; }菜单程序的特点是至少要显示一次菜单让用户选所以用do-while就很合适。⚠️注意do-while最后的while后面有个分号很多新手会忘写或者写成和 while 一样的格式导致编译错误。四、for 循环for是 C 语言里最常用、最灵活的循环没有之一。4.1 基本语法for (表达式1; 表达式2; 表达式3) { // 循环体 }三个表达式分别是表达式 1初始化循环开始前执行一次表达式 2条件判断每次循环前都判断表达式 3更新每次循环体执行完后执行对应的就是循环三要素表达式 1 → 初始值表达式 2 → 条件表达式 3 → 更新4.2 执行流程① 执行表达式1只执行一次 ↓ ② 判断表达式2 ↓ ┌─ 为真 → ③ 执行循环体 │ ↓ │ ④ 执行表达式3 │ ↓ └── 回到第②步 ↓ 为假 → 结束循环文字描述有点绕来看个例子就懂了。4.3 第一个例子打印 1 到 5#include stdio.h int main() { int i; for (i 1; i 5; i) // ①初始 ②条件 ③更新 { printf(%d , i); } printf(\n循环结束\n); return 0; }运行结果1 2 3 4 5 循环结束和之前 while 的例子结果一样但代码更紧凑了 —— 把循环三要素都写在了一行里一目了然。我们来一步步走先执行i 1只执行一次判断i 5→ 15 为真 → 执行循环体打印 1执行i→ i 变成 2判断i 5→ 25 为真 → 执行循环体打印 2执行i→ i 变成 3…… 以此类推直到 i6 时条件为假结束是不是很清晰4.4 再看一个例子计算 1 加到 100#include stdio.h int main() { int i; int sum 0; for (i 1; i 100; i) { sum i; } printf(12...100 %d\n, sum); return 0; }运行结果12...100 5050和 while 版本功能一样但代码更简洁循环变量的初始化、条件、更新都集中在一起看着就舒服。4.5 for 循环的各种变体for循环非常灵活三个表达式都可以省略但分号不能省变体 1省略表达式 1如果循环变量已经初始化过了可以省略表达式 1int i 1; for (; i 5; i) // 第一个表达式空着但分号不能省 { printf(%d , i); }变体 2省略表达式 3如果更新操作写在循环体里了可以省略表达式 3for (i 1; i 5; ) { printf(%d , i); i; // 更新写在这里 }变体 3三个都省略三个都省略的话就变成死循环了for (;;) // 相当于 while(1) { printf(死循环\n); }变体 4C99 可以在 for 里定义变量C99 标准允许在for的表达式 1 里直接定义变量for (int i 1; i 5; i) // 直接在for里定义i { printf(%d , i); }这样写更方便而且变量i的作用域只在for循环里面外面用不了 —— 更安全。建议如果编译器支持 C99现在基本都支持推荐在for里面直接定义循环变量代码更简洁作用域也更清晰。五、三种循环怎么选三种循环都能实现循环功能什么时候用哪个循环特点适用场景while先判断后执行不知道循环次数靠条件控制do-while先执行后判断至少一次菜单、输入验证等需要先执行一次的for最灵活三要素集中知道循环次数或者有明确的循环变量简单记知道循环多少次 → 优先用for不知道多少次靠条件判断 → 用while至少要执行一次 → 用do-while其实用多了你会发现for能搞定绝大多数场景是当之无愧的 循环一哥。六、break 和 continue循环里还有两个重要的关键字break和continue用来 打乱 正常的循环流程。6.1 break跳出整个循环break的作用是立即跳出当前循环循环就结束了。#include stdio.h int main() { int i; for (i 1; i 10; i) { if (i 5) { break; // 遇到5就跳出循环 } printf(%d , i); } printf(\n循环结束i %d\n, i); return 0; }运行结果1 2 3 4 循环结束i 5本来要循环到 10 的但是 i 等于 5 的时候遇到了break直接跳出了循环后面的 5、6、7... 都不执行了。注意break只能跳出一层循环。如果是嵌套循环内层的 break 只能跳出内层跳不到外层。6.2 continue跳过本次循环continue的作用是跳过本次循环的剩余部分直接进入下一次循环。#include stdio.h int main() { int i; for (i 1; i 10; i) { if (i % 2 0) { continue; // 偶数就跳过不打印 } printf(%d , i); } printf(\n循环结束\n); return 0; }运行结果1 3 5 7 9 循环结束遇到偶数的时候continue跳过了后面的printf直接进入下一次循环。所以只打印了奇数。6.3 break 和 continue 的区别关键字作用影响范围break跳出整个循环循环直接结束continue跳过本次继续下一次只影响当前这一次简单记break 不干了下班 → 整个循环结束continue 这次跳过下次继续 → 只跳过这一轮七、循环嵌套循环里面还可以再写循环这叫循环嵌套。最经典的例子就是九九乘法表#include stdio.h int main() { int i, j; for (i 1; i 9; i) // 外层循环控制行 { for (j 1; j i; j) // 内层循环控制列 { printf(%d×%d%-2d , j, i, i * j); } printf(\n); // 一行打完了换行 } return 0; }运行结果1×11 1×22 2×24 1×33 2×36 3×39 1×44 2×48 3×412 4×416 ...嵌套循环的执行逻辑外层循环走一次内层循环要走完整的一轮。就像时钟外层 分针内层 秒针分针走一格秒针要走一圈九九乘法表中i1 时j 从 1 到 1 → 打 1 个式子i2 时j 从 1 到 2 → 打 2 个式子i3 时j 从 1 到 3 → 打 3 个式子...i9 时j 从 1 到 9 → 打 9 个式子总共执行了 123...9 45 次内层循环体。注意嵌套循环的效率是 相乘 的关系。外层 100 次内层 100 次总共就是 10000 次。所以嵌套层数不要太多一般 2-3 层就够了再多程序就会变慢。八、综合示例学了这么多让我们来看几个经典的循环练习。示例 1判断素数#include stdio.h int main() { int n; int i; int is_prime 1; // 假设是素数1表示是0表示不是 printf(请输入一个正整数); scanf(%d, n); if (n 2) { printf(%d不是素数\n, n); return 0; } // 从2试到n-1看有没有能整除的 for (i 2; i n; i) { if (n % i 0) { is_prime 0; // 找到了能整除的不是素数 break; // 找到了就不用再试了直接跳出 } } if (is_prime) { printf(%d是素数\n, n); } else { printf(%d不是素数\n, n); } return 0; }示例 2打印三角形#include stdio.h int main() { int n 5; // 打印5行 int i, j; for (i 1; i n; i) // 外层行 { // 先打空格 for (j 1; j n - i; j) { printf( ); } // 再打星号 for (j 1; j 2 * i - 1; j) { printf(*); } printf(\n); } return 0; }运行结果* *** ***** ******* *********九、本节小结本节我们学习了 C 语言的三种循环结构以及两个循环控制关键字1. 三种循环表格循环语法特点whilewhile(条件) { ... }先判断后执行可能一次都不执行do-whiledo { ... } while(条件);先执行后判断至少执行一次forfor(初始; 条件; 更新) { ... }最灵活三要素集中最常用2. 循环三要素初始值从哪里开始条件判断什么时候结束更新每次改变什么⚠️ 三者缺一不可否则容易死循环3. break 和 continuebreak跳出整个循环不干了continue跳过本次继续下一次4. 循环嵌套循环里面套循环外层走一次内层走一轮注意嵌套不要太深影响效率学习建议循环是编程的基本功中的基本功一定要多练。建议你把经典的循环题都做一遍打印各种图形、求和、求阶乘、判断素数、斐波那契数列…… 练到随手就能写出来才算真正掌握了。⚠️ 关于本文由于笔者水平有限文中难免存在疏漏、错误或表述不够准确的地方。如果你在阅读过程中发现了任何问题 —— 无论是概念错误、代码 bug、还是表述不清 —— 都欢迎在评论区留言指正我会及时修正。技术之路道阻且长行则将至。我们互相学习共同进步