5. 流程控制(二):while循环、do-while循环、for循环、break与continue、循环嵌套

循环,说白了就是让计算机反复干同一件事。你让它打印100遍"Hello",它绝不会喊累。但写代码的人得想清楚:什么时候停?怎么停?停不下来怎么办?

我刚开始学C语言时,觉得循环不就是个"重复执行"嘛,有啥好讲的。直到有一次写串口接收程序,循环条件写反了,程序直接卡死,板子上的LED灯疯狂闪烁——嗯,从那以后我再也不敢小看循环了。

5.1 while循环:先判断,再执行

while循环的格式很简单:

while (条件表达式) {
    // 循环体
    // 当条件为真时反复执行
}

它的执行逻辑是:先判断条件,条件成立才进入循环体。如果一开始条件就不成立,循环体一次都不执行。

举个例子,我想计算1加到100:

#include <stdio.h>

int main() {
    int i = 1;
    int sum = 0;
    
    while (i <= 100) {
        sum += i;
        i++;
    }
    
    printf("1+2+...+100 = %d\n", sum);
    return 0;
}

这里有个关键点:循环变量i必须在循环体内更新。如果你忘了写i++,i永远等于1,条件永远成立——死循环就来了。

⚠️ 我曾经犯过的错:写while循环时,条件表达式里用了赋值号"="而不是比较符"=="。比如 while (i = 100),这会把100赋给i,而100是非零值,条件永远为真。调试了一下午才发现。

5.2 do-while循环:先执行,再判断

do-while和while的区别就一句话:do-while至少执行一次循环体

do {
    // 循环体
} while (条件表达式);

注意末尾有个分号,别漏了。我见过不少新手在这里栽跟头。

什么时候用do-while?比如你要从键盘读取数据,直到读到合法值为止。先读一次,如果不对再继续读:

int value;
do {
    printf("请输入一个正数:");
    scanf("%d", &value);
} while (value <= 0);

我个人习惯是:能确定至少执行一次的场景,用do-while;否则用while。这样代码意图更清晰。

5.3 for循环:最常用的循环

for循环把初始化、条件判断、循环变量更新都写在一行里:

for (初始化; 条件; 更新) {
    // 循环体
}

还是1加到100的例子,用for写更紧凑:

int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}

三个部分都可以省略,但分号不能省。比如 for(;;) 就是死循环——我有时在嵌入式主循环里这么写,配合break跳出。

💡 我的经验:for循环的初始化部分可以声明变量(C99标准支持),但要注意变量的作用域只在循环体内。如果你需要在循环结束后还访问这个变量,就在外面声明。

5.4 break与continue:循环的"刹车"和"跳过"

这两个关键字是循环里的控制利器。

  • break:立即跳出整个循环,不再执行后续迭代。
  • continue:跳过本次循环的剩余部分,直接进入下一次迭代。

看个例子:

for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        break;  // i等于5时跳出循环
    }
    printf("%d ", i);
}
// 输出:1 2 3 4
for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        continue;  // i等于5时跳过本次,继续下一次
    }
    printf("%d ", i);
}
// 输出:1 2 3 4 6 7 8 9 10

我在项目中遇到过一个问题:用break跳出嵌套循环时,它只跳出最内层循环。如果你要跳出多层,要么用goto(不推荐),要么加一个标志变量。

🔑 关键区别:break是"我不干了,全结束";continue是"这次算了,下次继续"。别搞混了。

5.5 循环嵌套:循环里面套循环

循环嵌套很常见,比如打印九九乘法表:

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= i; j++) {
        printf("%d*%d=%2d ", j, i, i*j);
    }
    printf("\n");
}

外层循环控制行数,内层循环控制每行的列数。嵌套层数多了,时间复杂度会急剧上升——三层循环就是O(n³),数据量一大就卡死。

我记得有一次做图像处理,用了四层嵌套循环处理640×480的图像,结果一帧要算好几秒。后来优化成查表法,才降到毫秒级。所以嵌套循环虽好用,但别滥用。

5.6 三种循环的选择建议

循环类型 适用场景 执行次数
while 条件驱动,不确定次数 0次或多次
do-while 至少执行一次 1次或多次
for 已知循环次数 0次或多次

说白了,for循环用得最多,因为它结构清晰。while适合"等到某个条件成立就停"的场景。do-while用得最少,但某些场景下它是唯一选择。

5.7 知识体系图

下面这张图帮你理清本章的知识脉络:

C语言循环结构 while循环 先判断条件 条件为真才执行 可能执行0次 do-while循环 先执行一次 再判断条件 至少执行1次 for循环 初始化;条件;更新 结构最紧凑 最常用 控制语句 break:跳出循环 continue:跳过本次 循环嵌套:内层+外层

5.8 避坑指南

  • 死循环:循环条件永远为真,或者循环变量不更新。嵌入式开发中偶尔故意用死循环(比如主循环),但一定要有退出机制。
  • 循环变量类型:用int没问题,但循环次数超过65535时注意别用short。我吃过这个亏。
  • break只跳一层:嵌套循环里想跳出多层?用标志变量或者把循环封装成函数,用return。
  • 分号别乱加:for后面加个分号,循环体就成空语句了。比如 for(i=0;i<10;i++); 后面的大括号只执行一次。

循环这东西,写多了自然就熟了。刚开始觉得绕,多写几个例子就通了。记住一点:循环是让计算机干活,不是让你自己干。能用循环解决的问题,别手写重复代码。


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