前几篇文章,我们让程序有了记忆(变量),会说话(输入输出),还学会了判断(分支)。但程序还有一个让人类望尘莫及的本事:不知疲倦地重复做一件事。
想想看,让你把“你好”写 100 遍,你可能会烦;但程序用一个循环,不到一毫秒就能完成。循环是计算机真正的效率利器,它能把几行代码的执行次数放大成千上万倍。
C 语言给了你三把循环的工具:while、do-while、for,外加两个控制循环走向的关键字 break 和 continue。今天我们就来掌握它们。
一、while 循环:先问再做
while 循环的逻辑最简单:只要条件成立,就重复执行循环体。每次执行前都会先检查条件,如果一开始就不成立,循环体一次都不会执行。
while (条件) {
// 循环体
}
一个最经典的例子——从 1 数到 5:
#include <stdio.h>
int main(void) {
int i = 1; // 初始化
while (i <= 5) { // 条件
printf("%d ", i);
i++; // 更新循环变量
}
printf("\n");
return 0;
}
输出:
1 2 3 4 5
如果把 i++ 忘掉,i 永远是 1,条件永远成立,程序就会陷入无限循环。写 while 循环时,一定问自己三个问题:
- 循环变量初始化了没有?
- 条件最终会不会变成假?
- 每次循环有没有朝“假”的方向前进一步?
这三个问题是防止死循环的“三把锁”。
二、do-while 循环:先做再问
while 的变体,它把条件检查挪到了循环体之后。这意味着不管条件如何,循环体至少执行一次。
do {
// 循环体
} while (条件);
注意:while (条件); 后面的分号不能少——这是初学者最容易掉的坑之一。
一个典型的场景:要求用户输入一个正数,不合法就一直提示重新输入。
#include <stdio.h>
int main(void) {
int number;
do {
printf("请输入一个正数:");
scanf("%d", &number);
} while (number <= 0);
printf("你输入了 %d,谢谢!\n", number);
return 0;
}
用户的输入在循环体里读,然后再判断。因为“读”的动作必须先执行一次,所以用 do-while 比 while 更自然。
三、for 循环:最紧凑的循环体
大多数循环都有三步曲:初始化、条件检查、更新循环变量。for 循环把它们一行搞定,让代码紧凑易读。
for (初始化; 条件; 更新) {
// 循环体
}
执行顺序是:
- 执行初始化(只执行一次)
- 检查条件,如果为假则退出循环
- 执行循环体
- 执行更新
- 跳回第 2 步
用 for 重写 1 到 5 的计数:
for (int i = 1; i <= 5; i++) {
printf("%d ", i);
}
括号里三个部分都可以省略(分号必须保留),但省略要有充足理由。比如:
for (; i < 10; i++):初始化放到外面for (;;):无限循环(等价于while(1))
for 循环里声明的变量(如 int i)在 C99 标准中是允许的,作用域仅限于循环内。如果你的编译器比较老(如某些 C89 模式),可能需要把变量声明提到循环外。
四、break 与 continue:循环的半路控制
有时候循环不必傻傻跑到条件变为假,可以在中途就跳出,或者跳过剩下的部分直接开始下一轮。这就需要 break 和 continue。
break:直接跳出循环
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // 碰到 5 就终止整个循环
}
printf("%d ", i);
}
输出:1 2 3 4(i=5 时直接跳出,后面的 6-10 都不打)
continue:跳过本轮剩余部分,进入下一轮
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 跳过 i=3 时的打印,直接去 i++
}
printf("%d ", i);
}
输出:1 2 4 5(3 被跳过了)
注意:在 while 和 do-while 里用 continue 要特别小心——它会跳转到条件检查处,可能导致更新语句被跳过而形成死循环。比如:
int i = 0;
while (i < 5) {
if (i == 2) continue;
printf("%d ", i);
i++; // 当 i=2 时 continue,i++ 被跳过,永远停在 2,死循环
}
所以在 while 里用 continue,要确保变量的更新发生在 continue 之前。
五、嵌套循环与经典案例:九九乘法表
循环里面可以再套循环,形成嵌套循环。外循环每执行一次,内循环就会完整地跑一遍。它常用来处理二维表格、矩阵、图形打印等问题。
一个最典型的例子:打印九九乘法表。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 9; i++) { // 外循环控制行
for (int j = 1; j <= i; j++) { // 内循环控制列,注意 j <= i 形成下三角
printf("%d×%d=%-2d ", j, i, i * j);
}
printf("\n"); // 一行结束,换行
}
return 0;
}
输出:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16
...
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
%-2d 表示左对齐占 2 个宽度,让排版整齐。试试把 j <= i 改成 j <= 9,你就会看到完整的矩形表,而不仅仅是下三角。
嵌套循环时注意:内循环变量和外循环变量不要用同一个名字(除非你非常清楚作用域规则),不然内层的修改会干扰外层。
六、三大循环的选择指南
| 场景 | 推荐 | 原因 |
|---|---|---|
| 循环次数已知(如遍历数组) | for | 初始、条件、更新集中,清晰 |
| 循环次数未知,先判断再执行 | while | 条件在最前面,符合直觉 |
| 循环次数未知,至少执行一次 | do-while | 体在条件前,保证首次执行 |
实际使用中,for 和 while 可以互相转换,大多数场景用 for 就能胜任。但当你需要先读数据再判断是否继续时,do-while 就展现出它的优势。
七、常见错误与陷阱
-
while后多加分号int i = 0; while (i < 5); { // 分号让循环体变成空的,死循环 printf("%d", i); i++; } -
do-while后忘分号
do { ... } while (cond)末尾必须带分号。 -
循环变量忘记更新
while体内缺少i++,导致死循环。 -
for括号里用逗号替代分号
for (int i = 0, i < 10, i++)错误,分号必须保留。 -
在
while/do-while中用continue导致更新跳过
如前例,务必先更新再continue,或者改用for循环。 -
循环边界错误
比如i <= 10写成i < 10,会少一次。初学者要仔细检查边界。
八、小结
循环让程序有了重复执行的能力,结合之前学的变量和分支,你已经可以写出有逻辑的、能处理批量数据的小程序了。while、do-while、for 各有适用的场合,break 和 continue 给了你更精细的控制。嵌套循环则打开了处理二维问题的大门。
但很快你会面临一个新问题:如果我想存一个班所有学生的成绩,难道要声明 score1、score2……score50 这样 50 个变量吗?那显然太蠢了。下一篇文章,我们就迎来一个重要的新工具——数组,它能让你用一个名字管理一串数据,让程序处理大量数据变得轻而易举。
课后小练习
- 用
while循环计算 1 到 100 的累加和并输出。 - 用
for循环打印斐波那契数列的前 20 项(1, 1, 2, 3, 5, 8…),每行输出 5 个数。 - 用嵌套循环打印如下图形:
* ** *** **** ***** - 写一个猜数字游戏:程序预设一个 1-100 的整数(可以先固定写死一个值),让用户猜,每次猜完提示“大了”或“小了”,直到猜中为止。统计猜了多少次。用
do-while或while实现。
题外话
如果你正在学C语言或计划学C语言,请订阅免费专栏《C语言:从入门到精通》。这是一个循序渐进的 C 语言博客系列,从最基础的环境搭建一路到高阶的系统编程技巧,帮你构建一个完整的知识体系。不需要积分,不需要VIP!
我们下期见!

1730

被折叠的 条评论
为什么被折叠?



