第七章 流程控制(二):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 本章知识体系

下面这张图帮你理清本章的核心逻辑:

C语言循环结构知识体系 while 循环 do-while 循环 for 循环 循环嵌套 break(跳出循环) continue(跳过本次) 先判断后执行 | 至少执行一次 | 计数循环

我的个人建议:初学者先把 for 循环练熟,它最常用、最直观。等 for 循环信手拈来了,再回头看看 while 和 do-while 的细微差别。别一口气吃成胖子——循环这东西,写 50 遍自然就懂了。


公众号:蓝海资料掘金营,微信deep3321