第七章 流程控制(二):while、do-while、for 与循环嵌套
循环,说白了就是让计算机反复干同一件事。你想想看,要是没有循环,让你打印 1 到 100,你得写 100 行 printf——那画面太美我不敢看。C 语言给了我们三种循环武器:while、do-while 和 for。我个人习惯把它们分成两类:“先判断再干活” 和 “先干一次再说”。
7.1 while 循环:先看门,再进门
while 的语法很简单:
while (条件表达式) {
// 循环体
}
每次执行循环体之前,先检查条件。条件为真,进去执行;条件为假,直接跳过。我在项目中遇到过不少新手写 while 循环忘记更新条件变量,结果成了死循环。嗯,这里要注意:循环体里一定要有改变条件的机会。
经典例子:计算 1 到 100 的和。
int i = 1, sum = 0;
while (i <= 100) {
sum += i;
i++; // 别忘了这行
}
printf("sum = %d\n", sum);
我曾经见过一个同事,while 条件里写了个分号:while(i <= 100); 结果程序卡死了一下午。分号代表空语句,循环体是空的,条件永远不变——死循环没跑了。
7.2 do-while 循环:先进门,再看门
do-while 和 while 的唯一区别:至少执行一次循环体。
do {
// 循环体
} while (条件表达式); // 注意这里的分号不能少
什么时候用 do-while?我举个例子:你要从键盘读一个数,直到用户输入 0 为止。第一次读的时候根本不知道用户会输什么,但总得先读一次吧?这时候 do-while 就派上用场了。
避坑指南:我曾经在 do-while 后面忘了加分号,编译报错找了十分钟。记住:while(...); 这个分号是 do-while 语法的一部分,不是语句结束符。
7.3 for 循环:最常用的循环
for 循环把初始化、条件判断、变量更新都写在一行里,结构清晰:
for (初始化; 条件; 更新) {
// 循环体
}
说白了,for 循环就是 while 的“语法糖”。上面的 1 到 100 求和用 for 写:
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
我个人习惯用 for 循环遍历数组,因为它的三个部分一目了然。你想想看,要是用 while 遍历数组,初始化在循环外面,更新在循环体里面,读代码的时候还得上下找——多累啊。
注意:for 循环的三个表达式都可以省略,但分号不能省。比如 for(;;) 就是死循环。我在调试时偶尔会用这个技巧临时卡住程序,但正式代码里千万别这么写。
7.4 循环嵌套:循环里面套循环
循环嵌套就是在一个循环体里再写一个循环。最常见的场景是处理二维数组,或者打印九九乘法表。
// 打印九九乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%d*%d=%2d ", j, i, i * j);
}
printf("\n");
}
我在项目中遇到过三层循环嵌套的情况,处理图像像素矩阵。那时候我特别注意内层循环的变量名不要和外层冲突——你想想看,要是内外都用 i,程序就乱套了。
性能提示:循环嵌套时,把循环次数多的放在内层,可以减少 CPU 的循环控制开销。比如外层循环 10 次、内层 1000 次,比外层 1000 次、内层 10 次效率高。为什么?因为外层循环每次都要重新初始化内层循环,次数越少越好。
7.5 break 与 continue:循环的“刹车”和“跳过”
break 是跳出整个循环,continue 是跳过本次循环的剩余部分,直接进入下一次。
| 关键字 | 作用 | 适用场景 |
|---|---|---|
| break | 立即终止当前循环 | 找到目标后提前退出 |
| continue | 跳过本次循环剩余代码 | 过滤掉不符合条件的数据 |
举个例子:从数组里找第一个负数,找到了就停止——用 break:
int arr[] = {3, 5, -1, 7, 2};
for (int i = 0; i < 5; i++) {
if (arr[i] < 0) {
printf("找到负数:%d\n", arr[i]);
break; // 找到了,后面的不用看了
}
}
再比如:打印 1 到 10 中所有不是 3 的倍数的数——用 continue:
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) {
continue; // 跳过 3 的倍数
}
printf("%d ", i);
}
我曾经踩过的坑:在嵌套循环里用 break,它只跳出最内层的那一层循环。如果你想跳出多层循环,要么用 goto(不推荐),要么加一个标志变量来控制。别指望一个 break 能帮你跳出三层循环——它没那个本事。
7.6 三种循环的选择建议
- 知道循环次数(比如遍历数组)→ 用 for
- 不知道次数,但知道什么时候结束(比如读文件直到 EOF)→ 用 while
- 至少需要执行一次(比如菜单选择)→ 用 do-while
说白了,没有绝对的“哪个更好”,只有“哪个更合适”。我写代码的时候,80% 的情况用 for,15% 用 while,5% 用 do-while。你写多了自然就有感觉了。
7.7 本章知识体系
下面这张图帮你理清本章的核心逻辑:
我的个人建议:初学者先把 for 循环练熟,它最常用、最直观。等 for 循环信手拈来了,再回头看看 while 和 do-while 的细微差别。别一口气吃成胖子——循环这东西,写 50 遍自然就懂了。
公众号:蓝海资料掘金营,微信deep3321