🛡️

身份验证

答对题目即可进入,验证你是谁

剩余尝试次数:3

循环 — for/while 重复执行

C语言学习教程

循环 — for/while 重复执行

🌟 生活中的”循环”

生活中到处都是循环:

程序也是一样。当你需要做重复的事情时,不可能把同一段代码复制粘贴 100 遍。循环就是用来解决”重复执行”的问题——写一次,执行多次

一句话总结:循环让一段代码能够反复运行。C 语言提供了三种循环方式:forwhiledo-while,外加 breakcontinue 两个控制开关。


📖 概念详解 — 三种循环,各司其职

循环的四要素

任何循环都包含四个要素,缺一不可:

要素说明示例
① 初始化循环开始前的准备工作int i = 0;
② 条件每次循环前检查,决定继续还是退出i < 10;
③ 循环体每次循环要执行的代码printf(...)
④ 更新每次循环后改变条件变量i++;

缺少任何一个要素,循环要么不执行,要么停不下来(死循环)。

for 循环流程

                ┌──────────────┐
                │ ① 初始化      │ ← 只执行一次
                │ int i = 0;    │
                └──────┬───────┘

                  ┌────▼────┐
                  │ ② 条件?  │ ← 每次循环前检查
                  │ i < 5?   │
                  └────┬─────┘
              真 ╱      ╲ 假
                 ▼        ▼
         ┌──────────┐   ┌──────────┐
         │ ③ 循环体  │   │ 退出循环  │
         │ printf   │   └──────────┘
         └────┬─────┘


         ┌──────────┐
         │ ④ 更新    │ ← 每次循环后执行
         │ i++       │
         └────┬─────┘

              └────→ 回到 ②

while 循环流程

                ┌──────────────┐
                │ 初始化在循环   │
                │ 之前完成      │
                └──────┬───────┘

                  ┌────▼────┐
             ┌───→│ 条件?   │ ← 先判断
             │    │ i < 5?   │
             │    └────┬─────┘
             │  真 ╱     ╲ 假
             │     ▼       ▼
             │  ┌──────┐  ┌──────┐
             │  │循环体 │  │ 退出  │
             │  └──┬───┘  └──────┘
             │     │
             │     ▼
             │  ┌──────┐
             │  │ 更新  │ ← 循环体内手动写
             │  │ i++   │
             │  └──┬───┘
             │     │
             └─────┘

do-while 循环流程(关键区别)

                ┌──────────────┐
                │ 初始化在循环   │
                │ 之前完成      │
                └──────┬───────┘

                  ┌────▼────┐
             ┌───→│ 循环体  │ ← 先执行!
             │    │ 更新    │    不管条件先跑一次
             │    └──┬─────┘
             │       │
             │  ┌────▼────┐
             │  │ 条件?   │ ← 执行完再判断
             │  │ i < 5?   │
             │  └────┬─────┘
             │  真 ╱     ╲ 假
             │     ▼       ▼
             └─────┘     ┌──────┐
                         │ 退出  │
                         └──────┘

核心对比while 是”先检查再进门”,do-while 是”先进门再检查”——所以 do-while 至少执行一次。


💻 代码示例 — 从计数器到实用场景

示例 1:for 循环 — 打印 1 到 10

#include <stdio.h>

int main() {
    printf("正序打印 1 到 10:\n");
    for (int i = 1; i <= 10; i++) {
        //  i=1 → 打印 → i=2 → 打印 → ... → i=10 → 打印 → i=11 → 退出
        printf("第 %d 次循环,i = %d\n", i, i);
    }

    printf("\n倒序打印 10 到 1:\n");
    for (int i = 10; i >= 1; i--) {
        printf("%d ", i);
    }
    printf("\n发射!🚀\n");

    return 0;
}

拆解 for 的三个部分

循环走了 10 次,i 的值依次是 1, 2, 3, …, 10。当 i 变成 11 时,i <= 10 为假,退出。


示例 2:for 循环 — 灵活使用(步长、多变量)

#include <stdio.h>

int main() {
    // 步长为 2:打印 0 到 20 的偶数
    printf("0 到 20 的偶数:\n");
    for (int i = 0; i <= 20; i += 2) {
        printf("%d ", i);
    }
    printf("\n\n");

    // 步长为 5:打印 0 到 100 的 5 的倍数
    printf("0 到 100 中 5 的倍数:\n");
    for (int i = 0; i <= 100; i += 5) {
        printf("%d ", i);
    }
    printf("\n\n");

    // 双变量:一头一尾向中间靠拢
    printf("双变量向中间靠拢:\n");
    for (int left = 1, right = 10; left <= right; left++, right--) {
        printf("left = %d, right = %d\n", left, right);
    }

    // 循环变量提前声明(C99 前必须这样写)
    printf("\n老式写法(变量在 for 外声明):\n");
    int i;
    for (i = 0; i < 3; i++) {
        printf("%d ", i);
    }
    printf("\n循环结束后 i = %d(在外面还能用!)\n", i);

    return 0;
}

注意:在 for(int i = 0; ...) 中声明的 i,只在循环内部有效。如果需要在循环后继续使用 i,要在 for 之前声明。


示例 3:while — 不知道循环多少次时使用

#include <stdio.h>

int main() {
    int num;
    int sum = 0;
    int count = 0;

    printf("请输入若干个整数(输入 0 结束):\n");

    // 不知道用户会输多少个数字 → 用 while
    printf("第 1 个数: ");
    scanf("%d", &num);

    while (num != 0) {     // num 不为 0 就一直循环
        sum += num;        // 累加
        count++;           // 计数
        printf("第 %d 个数: ", count + 1);
        scanf("%d", &num);
    }

    if (count > 0) {
        printf("\n共输入 %d 个有效数字\n", count);
        printf("总和 = %d\n", sum);
        printf("平均值 = %.2f\n", (double)sum / count);
    } else {
        printf("没有输入任何有效数字。\n");
    }

    return 0;
}

while 的典型场景


示例 4:do-while — 至少执行一次

#include <stdio.h>

int main() {
    int password = 1234;
    int input;
    int attempts = 0;
    const int MAX_ATTEMPTS = 3;

    // 至少让用户输入一次密码
    do {
        printf("请输入密码: ");
        scanf("%d", &input);
        attempts++;

        if (input == password) {
            printf("✅ 密码正确!欢迎回来。\n");
            break;  // 密码对了就退出
        } else {
            printf("❌ 密码错误");
            if (attempts < MAX_ATTEMPTS) {
                printf(",还剩 %d 次机会。\n", MAX_ATTEMPTS - attempts);
            } else {
                printf(",次数已用完!\n");
            }
        }
    } while (input != password && attempts < MAX_ATTEMPTS);

    if (attempts >= MAX_ATTEMPTS && input != password) {
        printf("账户已锁定,请稍后重试。\n");
    }

    return 0;
}

do-while 的典型场景


示例 5:break 与 continue — 循环的控制开关

#include <stdio.h>

int main() {
    // ========== break:立即退出循环 ==========
    printf("=== break 演示 ===\n");
    printf("遇到第一个能被 7 整除的数就停止:\n");

    for (int i = 1; i <= 100; i++) {
        if (i % 7 == 0) {
            printf("找到了:%d 能被 7 整除!\n", i);
            break;  // 立刻跳出循环,后面的 i 都不检查
        }
    }
    // 输出:找到了:7 能被 7 整除!

    printf("\n=== 在嵌套循环中用 break ===\n");
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 5; j++) {
            if (j == 3) {
                printf("  内层 j=%d 触发了 break\n", j);
                break;  // 只跳出内层循环!
            }
            printf("  i=%d, j=%d\n", i, j);
        }
        printf("外层 i=%d 继续...\n", i);
    }
    // 注意:break 只跳出最近的一层循环,外层不受影响

    // ========== continue:跳过本次循环,继续下一次 ==========
    printf("\n=== continue 演示 ===\n");
    printf("打印 1-20 中的奇数(跳过偶数):\n");

    for (int i = 1; i <= 20; i++) {
        if (i % 2 == 0) {
            continue;  // 偶数就跳过,不执行后面的 printf
        }
        printf("%d ", i);
    }
    printf("\n");

    // 统计非跳过的次数
    printf("\n统计 1-100 中不能被 3 整除的数的个数:\n");
    int count = 0;
    for (int i = 1; i <= 100; i++) {
        if (i % 3 == 0) {
            continue;  // 能被 3 整除就跳过
        }
        count++;
    }
    printf("共有 %d 个(预期 100 - 33 = 67)\n", count);

    return 0;
}

记忆口诀


示例 6:嵌套循环 — 经典九九乘法表

#include <stdio.h>

int main() {
    printf("=====================\n");
    printf("   九九乘法表\n");
    printf("=====================\n");

    // 外层循环:被乘数 i(行)
    for (int i = 1; i <= 9; i++) {
        // 内层循环:乘数 j(列)
        for (int j = 1; j <= i; j++) {
            // %-4d 表示左对齐,占 4 个字符宽度
            printf("%d×%d=%-4d", j, i, i * j);
        }
        printf("\n");  // 每行结束换行
    }

    printf("\n详细解读:\n");
    printf("外层 i=1 时,内层 j 从 1 到 1 → 打印 1×1=1\n");
    printf("外层 i=2 时,内层 j 从 1 到 2 → 打印 1×2=2  2×2=4\n");
    printf("外层 i=3 时,内层 j 从 1 到 3 → 打印 3 个式子\n");
    printf("...\n");
    printf("外层每执行 1 次,内层执行一整轮\n\n");

    // 用表格展示嵌套循环的执行顺序
    printf("执行顺序追踪(部分):\n");
    printf("i=1, j=1  |  i=2, j=1  |  i=2, j=2  |  i=3, j=1  |  i=3, j=2  |  i=3, j=3  |  ...\n");

    return 0;
}

嵌套循环执行规律:外层一次,内层一轮。总执行次数 = 外层次数 × 内层次数。


⚠️ 常见错误 — 循环写不对,问题多在这些地方

错误 1:while 后面多了分号(死循环!)

错误写法正确写法
while (i < 5);while (i < 5)
// ❌ 错误演示(这段代码会卡死!)
int i = 0;
while (i < 5); {    // 分号!while 在一个空语句上死循环
    printf("%d\n", i);
    i++;
}
// i 永远是 0,条件永远为真,程序卡死!

// ✅ 正确写法
int i = 0;
while (i < 5) {     // 没有分号
    printf("%d\n", i);
    i++;
}
// 输出:0 1 2 3 4

和 if 一样,一个逗号就能毁掉整个循环。


错误 2:忘记更新循环变量(死循环!)

// ❌ 错误演示
int i = 0;
while (i < 5) {
    printf("%d ", i);
    // 忘记 i++!
}
// i 永远为 0,死循环!

// ✅ 正确写法
int i = 0;
while (i < 5) {
    printf("%d ", i);
    i++;   // 必须更新!
}

错误 3:循环变量的作用域问题

#include <stdio.h>

int main() {
    // ❌ 在 for 内部声明的变量,循环外不可用
    for (int i = 0; i < 5; i++) {
        printf("%d ", i);
    }
    // printf("%d", i);  // 编译错误!i 已不在作用域内

    // ✅ 如果需要在循环外使用 i
    int i;
    for (i = 0; i < 5; i++) {
        printf("%d ", i);
    }
    printf("\n循环结束后 i = %d\n", i);  // OK,输出 5

    return 0;
}

错误 4:嵌套循环用同一个变量名

// ❌ 错误演示
for (int i = 1; i <= 3; i++) {
    for (int i = 1; i <= 3; i++) {  // 内外层都用 i!
        printf("*");                 // 内层的 i 会干扰外层
    }
    printf("\n");
}
// 行为不可预测!

// ✅ 正确写法:内外层用不同名字
for (int i = 1; i <= 3; i++) {      // 外层 i
    for (int j = 1; j <= 3; j++) {  // 内层 j
        printf("*");
    }
    printf("\n");
}

错误 5:边界条件差 1(off-by-one 错误)

// ❌ 想打印 10 次,结果打印了 11 次
for (int i = 0; i <= 10; i++) {  // 0,1,2,...,10 → 11 次!
    printf("%d ", i);
}

// 想打印 10 次,结果只打印了 9 次
for (int i = 1; i < 10; i++) {   // 1,2,...,9 → 9 次!
    printf("%d ", i);
}

// ✅ 打印 10 次的标准写法(任选一种)
for (int i = 0; i < 10; i++)     // 0,1,...,9 → 10 次 ✓
for (int i = 1; i <= 10; i++)    // 1,2,...,10 → 10 次 ✓

规则


错误 6:do-while 结尾忘记分号

// ❌ 编译错误
int i = 0;
do {
    printf("%d", i);
    i++;
} while (i < 5)   // 缺少分号!

// ✅ 正确写法
int i = 0;
do {
    printf("%d", i);
    i++;
} while (i < 5);  // do-while 结尾必须有分号

记忆技巧:while(...) 语句以分号结尾的,只有 do-while。普通 while 后面没有分号。


💡 练习建议

  1. 单步调试:用一个简单的 for 循环,在 IDE 中设置断点,单步执行观察 i 的变化。亲眼看着变量的值如何一步步变化,比任何文字解释都直观。
  2. 在纸上跑流程:遇到复杂的嵌套循环,用纸笔一行行追踪变量的值。这对建立循环的直觉非常有帮助。
  3. 改写练习:把一个 for 循环改成 while,再改成 do-while,体会三者的异同。并非所有循环都能互相改写(do-while 的”至少一次”语义 for/while 模拟不了)。
  4. 先写内层再写外层:写嵌套循环时,先把内层逻辑独立写对,再套上外层。
  5. 故意写死循环:写一个 while(1)for(;;),然后在里面用 break 退出。理解无限循环 + break 的设计模式(这在实际项目中很常见,比如服务器主循环)。

📝 要点速查

要点说明
for(初始化; 条件; 更新)三要素内聚,适合已知次数的循环
while(条件)先判断再执行,适合未知次数
do {...} while(条件);先执行再判断,至少一次
break立即退出当前循环(只退一层)
continue跳过本次循环剩余代码,继续下一次
嵌套循环外层一次 → 内层一轮
for(;;)无限循环(等价于 while(1)
循环四要素初始化、条件、循环体、更新,缺一不可

三种循环选择指南

需要循环 → 知道执行多少次?
              ├── 是 → 用 for
              └── 否 → 至少执行一次?
                        ├── 是 → 用 do-while
                        └── 否 → 用 while

🔗 相关主题