循环语句(Loop Statements)
循环让程序重复执行一段代码,直到满足终止条件。C 语言提供 for、while 和 do-while 三种循环结构,各有适用场景。
1. 为什么需要循环
没有循环时,重复操作只能复制粘贴:
printf("第 1 次\n");
printf("第 2 次\n");
printf("第 3 次\n");
// ...需要 100 次就要写 100 行
有了循环,几行代码搞定:
for (int i = 1; i <= 100; i++) {
printf("第 %d 次\n", i);
}
2. for 循环
2.1 基本语法
for (初始化; 条件; 更新) {
// 循环体
}
三部分的执行顺序:
初始化 → 判断条件 → 执行循环体 → 执行更新 → 判断条件 → 执行循环体 → 执行更新 → ...
↑_____________循环____________|
for (int i = 0; i < 5; i++) {
printf("i = %d\n", i);
}
// 输出:i = 0, i = 1, i = 2, i = 3, i = 4
2.2 执行流程详解
第 1 轮:i = 0 → 判断 0 < 5 为真 → 输出 i=0 → i++(i 变为 1)
第 2 轮:i = 1 → 判断 1 < 5 为真 → 输出 i=1 → i++(i 变为 2)
第 3 轮:i = 2 → 判断 2 < 5 为真 → 输出 i=2 → i++(i 变为 3)
第 4 轮:i = 3 → 判断 3 < 5 为真 → 输出 i=3 → i++(i 变为 4)
第 5 轮:i = 4 → 判断 4 < 5 为真 → 输出 i=4 → i++(i 变为 5)
第 6 轮:i = 5 → 判断 5 < 5 为假 → 结束循环
2.3 变体
// 递减循环
for (int i = 10; i > 0; i--) {
printf("%d\n", i); // 10, 9, 8, ..., 1
}
// 步长为 2
for (int i = 0; i < 10; i += 2) {
printf("%d\n", i); // 0, 2, 4, 6, 8
}
// 多个变量
for (int i = 0, j = 10; i < j; i++, j--) {
printf("i=%d, j=%d\n", i, j);
}
// 省略某些部分(均合法,但不能省略分号)
int i = 0;
for (; i < 10; i++) { ... } // 初始化在循环外完成
for (int i = 0; i < 10; ) { // 更新在循环体内完成
printf("%d\n", i);
i++;
}
for (;;) { // 无限循环(等价于 while(1))
// ...
}
2.4 C99 起的作用域
for (int i = 0; i < 5; i++) { // i 的作用域仅限于循环内
// ...
}
// 此处 i 不可见
// 旧标准(C89/C90)不支持上述写法,需这样:
int i;
for (i = 0; i < 5; i++) { ... }
3. while 循环
3.1 基本语法
while (条件) {
// 循环体
}
先判断条件,条件为真才进入循环体。如果条件一开始就为假,循环体一次也不执行。
int count = 5;
while (count > 0) {
printf("倒计时:%d\n", count);
count--;
}
// 输出:5, 4, 3, 2, 1
3.2 适用场景
while 最适合"事先不知道要循环多少次"的场景:
// 逐字符读取直到文件结束
int ch;
while ((ch = getchar()) != EOF) {
putchar(ch);
}
// 寻找第一个满足条件的值
int guess;
printf("猜数字(1-100):");
scanf("%d", &guess);
while (guess != 42) {
printf("不对,再试:");
scanf("%d", &guess);
}
printf("正确!\n");
4. do-while 循环
do {
// 循环体
} while (条件);
与 while 的唯一区别:先执行一次循环体,再判断条件。保证循环体至少执行一次。
int input;
do {
printf("请输入正数:");
scanf("%d", &input);
} while (input <= 0);
printf("你输入了:%d\n", input);
三种循环对比
| 特性 | for |
while |
do-while |
|---|---|---|---|
| 最少执行次数 | 0 | 0 | 1 |
| 适用场景 | 已知循环次数 | 循环次数不确定 | 至少执行一次 |
| 典型用法 | 遍历数组、计数器 | 读取文件、等待条件 | 输入验证、菜单交互 |
| 条件检查位置 | 循环体之前 | 循环体之前 | 循环体之后 |
5. break 与 continue
5.1 break——提前退出
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 立即跳出整个循环
}
printf("%d ", i);
}
// 输出:0 1 2 3 4
break 只跳出最内层的循环或 switch:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == 1) break; // 只跳出内层 for
printf("(%d,%d) ", i, j);
}
}
// 输出:(0,0) (1,0) (2,0)
5.2 continue——跳过本轮
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue; // 跳过本次循环的剩余部分
}
printf("%d ", i);
}
// 输出:1 3 5 7 9(只输出奇数)
| 语句 | 效果 |
|---|---|
break |
终止整个循环,跳到循环后的第一条语句 |
continue |
跳过本轮循环剩余代码,进入下一轮的条件判断 |
6. 循环选择指南
你知道要循环多少次吗?
├── 是(如遍历数组 100 个元素) → for 循环
│
└── 否
├── 可能一次都不执行 → while 循环
│
└── 至少执行一次 → do-while 循环
7. 常见模式
7.1 遍历数组
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
7.2 累加求和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("1 到 100 的和 = %d\n", sum); // 5050
7.3 查找元素
int arr[] = {3, 7, 2, 9, 5};
int target = 9;
int found = 0;
for (int i = 0; i < 5; i++) {
if (arr[i] == target) {
printf("找到了,索引 = %d\n", i);
found = 1;
break; // 找到即停止
}
}
if (!found) {
printf("未找到\n");
}
7.4 无限循环 + 条件退出
while (1) {
int cmd;
printf("输入命令(0 退出):");
scanf("%d", &cmd);
if (cmd == 0) break;
printf("执行命令 %d\n", cmd);
}
8. 常见错误
| 错误 | 后果 | 正确写法 |
|---|---|---|
for (int i = 0; i < 10; i++); |
多了分号,循环体为空 | 删除多余分号 |
while (x > 0); { ... } |
同上 | 删除 while 行末的分号 |
| 循环条件永真 | 无限循环,程序不终止 | 检查更新语句是否正确改变循环变量 |
数组越界:i <= n |
访问不存在的元素 | 使用 i < n(n 为元素个数) |
break 只跳出内层 |
外层循环继续执行 | 如需跳出所有循环,使用标志变量或 goto |
9. 总结
| 要点 | 说明 |
|---|---|
for |
已知循环次数时的首选,结构紧凑 |
while |
先判断后执行,适合次数不确定的场景 |
do-while |
先执行后判断,保证至少一次 |
break |
立即终止循环 |
continue |
跳过本轮,继续下一轮 |
| 循环变量控制 | 确保更新语句正确,避免死循环 |
| 检查行末分号 | 多余的 ; 会形成空循环体 |
作者: Qing | 修改日期: 2026-07-18