C: 循环结构
循环就像跑操场——只要没到终点就继续跑,条件满足就停。掌握循环,程序才不会只做一次就结束。
1. while 循环
while 是最基础的循环:先判断条件,为真则执行循环体,然后再判断,如此反复,直到条件为假。
C
#include <stdio.h>
int main(void) {
int count = 1;
while (count <= 5) {
printf("第 %d 圈\n", count);
count++;
}
printf("跑完了!\n");
return 0;
}
TEXT
📖 仅展示
第 1 圈
第 2 圈
第 3 圈
第 4 圈
第 5 圈
跑完了!
⚠️ 循环体内一定要有让条件最终为假的操作(如
count++),否则会变成死循环,程序永远不会停止。
(1) while 的适用场景
当循环次数不确定,取决于运行时条件时,用 while 最自然。例如读取输入直到特定值:
C
#include <stdio.h>
int main(void) {
int sum = 0;
int num = 0;
printf("输入正整数求和,输入0结束: ");
scanf("%d", &num);
while (num != 0) {
sum += num;
scanf("%d", &num);
}
printf("总和: %d\n", sum);
return 0;
}
TEXT
📖 仅展示
输入正整数求和,输入0结束: 10 20 30 0
总和: 60
2. do-while 循环
do-while 先执行循环体,再判断条件。保证循环体至少执行一次,这是它和 while 的关键区别。
C
#include <stdio.h>
int main(void) {
int num;
do {
printf("输入1-10的数字: ");
scanf("%d", &num);
} while (num < 1 || num > 10);
printf("你输入了: %d\n", num);
return 0;
}
TEXT
📖 仅展示
输入1-10的数字: 15
输入1-10的数字: 0
输入1-10的数字: 7
你输入了: 7
⚠️
do-while 末尾的分号不能省:} while (条件); 忘了分号会编译报错。
(1) while 与 do-while 的选择
- 至少执行一次 →
do-while(如输入验证) - 可能一次都不执行 →
while(如搜索可能找不到)
3. for 循环
for 把初始化、条件判断、更新三部分集中在头部,是最常用的循环形式。
C
for (初始化; 条件; 更新) {
循环体;
}
C
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 5; i++) {
printf("%d ", i);
}
printf("\n");
return 0;
}
TEXT
📖 仅展示
1 2 3 4 5
(1) for 的执行流程
- 执行初始化(仅一次)
- 判断条件——为假则退出循环
- 执行循环体
- 执行更新
- 回到第2步
(2) for 的灵活性
for 的三个部分都可以省略,但分号不能省:
C
#include <stdio.h>
int main(void) {
int i = 1;
for (; i <= 5; ) {
printf("%d ", i);
i++;
}
printf("\n");
return 0;
}
省略条件就变成死循环:for (;;) {} 等同于 while (1) {}。
💡 优先使用
for 循环——循环变量、边界条件、更新方式一目了然,不容易写出死循环。
(3) 作用域注意
C99 允许在 for 的初始化部分声明变量,该变量的作用域仅限于 for 循环内部:
C
#include <stdio.h>
int main(void) {
for (int i = 0; i < 3; i++) {
printf("i = %d\n", i);
}
return 0;
}
循环结束后 i 不再可用。如果需要在循环外使用 i,就要在 for 之前声明。
4. 嵌套循环
循环内部再放一个循环,就是嵌套循环。外层每执行一次,内层完整执行一轮。
(1) 打印矩形星号
C
#include <stdio.h>
int main(void) {
int rows = 3;
int cols = 5;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
TEXT
📖 仅展示
* * * * *
* * * *
* * * * *
(2) 九九乘法表
C
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%d*%d=%-4d", j, i, i * j);
}
printf("\n");
}
return 0;
}
TEXT
📖 仅展示
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
⚠️ 嵌套循环的总执行次数是外层次数×内层次数,3层嵌套就会急剧增长,注意性能。
5. break 语句
break 立即跳出当前循环(只跳一层),不再执行剩余循环。
C
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
printf("%d ", i);
}
printf("\n遇到5就跳出\n");
return 0;
}
TEXT
📖 仅展示
1 2 3 4
遇到5就跳出
(1) 查找第一个满足条件的元素
C
#include <stdio.h>
int main(void) {
int nums[] = {3, 7, 2, 9, 5, 1};
int target = 9;
int found = 0;
for (int i = 0; i < 6; i++) {
if (nums[i] == target) {
printf("找到 %d,下标 %d\n", target, i);
found = 1;
break;
}
}
if (!found) {
printf("未找到 %d\n", target);
}
return 0;
}
TEXT
📖 仅展示
找到 9,下标 3
6. continue 语句
continue 跳过当前这一轮循环的剩余语句,直接进入下一轮(回到条件判断或更新步骤)。
C
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) {
continue;
}
printf("%d ", i);
}
printf("\n3的倍数被跳过了\n");
return 0;
}
TEXT
📖 仅展示
1 2 4 5 7 8 10
3的倍数被跳过了
⚠️ 在
while 和 do-while 中使用 continue 要确保更新语句在 continue 之前,否则可能死循环。
7. 常见循环模式
(1) 计数模式
统计满足条件的元素个数:
C
#include <stdio.h>
int main(void) {
int nums[] = {12, 45, 3, 67, 89, 23, 56};
int count = 0;
for (int i = 0; i < 7; i++) {
if (nums[i] > 50) {
count++;
}
}
printf("大于50的有 %d 个\n", count);
return 0;
}
TEXT
📖 仅展示
大于50的有 3 个
(2) 累加模式
把一系列值加在一起:
C
#include <stdio.h>
int main(void) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("1到100的和: %d\n", sum);
return 0;
}
TEXT
📖 仅展示
1到100的和: 5050
(3) 搜索模式
查找第一个满足条件的元素,找到后用 break 退出:
参见前面 break 示例。
(4) 遍历模式
依次处理数组中的每个元素:
C
#include <stdio.h>
int main(void) {
int scores[] = {85, 92, 78, 96, 61};
int len = 5;
for (int i = 0; i < len; i++) {
printf("学生%d: %d分 %s\n", i + 1, scores[i], scores[i] >= 60 ? "及格" : "不及格");
}
return 0;
}
TEXT
📖 仅展示
学生1: 85分 及格
学生2: 92分 及格
学生3: 78分 及格
学生4: 96分 及格
学生5: 61分 及格
8. 死循环与避免
死循环是条件永远为真的循环。有意为之的死循环用 for(;;) 或 while(1),内部用 break 退出:
C
#include <stdio.h>
int main(void) {
int num;
while (1) {
printf("输入数字(0退出): ");
scanf("%d", &num);
if (num == 0) {
break;
}
printf("你输入了: %d\n", num);
}
printf("再见!\n");
return 0;
}
无意产生的死循环通常是因为忘记更新循环变量或更新方向错误:
C
int i = 0;
while (i < 10) {
printf("%d", i);
}
⚠️ 如果程序好像"卡住了"不动,第一个怀疑就是死循环。按 Ctrl+C 可以强制终止。
▶ 示例
用嵌套循环打印直角三角形:
C
#include <stdio.h>
int main(void) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
TEXT
📖 仅展示
*
* *
* * *
* * * *
* * * * *
▶ 示例
求两个正整数的最大公约数(辗转相除法),演示不确定次数的 while 循环:
C
#include <stdio.h>
int main(void) {
int a = 48, b = 18;
int orig_a = a, orig_b = b;
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
printf("%d 和 %d 的最大公约数是 %d\n", orig_a, orig_b, a);
return 0;
}
TEXT
📖 仅展示
48 和 18 的最大公约数是 6
9. 三种循环的选择
| 情况 | 推荐 |
|---|---|
| 循环次数确定 | for |
| 至少执行一次 | do-while |
| 循环次数不确定 | while |
| 交互式菜单 | do-while + switch |
💡 三种循环在逻辑上可以互相转换,选择最贴合业务场景的写法即可。
❓ 常见问题
Q
for 和 while 到底用哪个?A 循环次数确定时用
for,循环次数不确定时用 while。这是最通用的选择标准。Q
break 能跳出多层循环吗?A 不能。
break 只跳出最内层循环。要跳出多层,可以用标志变量配合外层判断,或者用 goto(不推荐但有时实用)。Q
for(;;) 和 while(1) 哪个好?A 功能完全等价。
while(1) 可读性更好,for(;;) 是传统C风格。选哪个看团队规范。Q 循环变量用
i、j、k 可以吗?A 简单循环中这是广泛接受的惯例。但如果变量有业务含义(如
row、col、student_index),用有意义的名字更好。📖 小节
while先判断再执行,do-while先执行再判断,for把三要素集中在头部for适合次数确定的循环,是最常用的循环结构- 嵌套循环的总次数等于各层次数的乘积,注意性能
break跳出当前循环,continue跳过当前一轮——都只作用于最内层- 避免无意死循环:确保循环变量在正确更新,方向正确
📝 作业
- 编写程序,用
for循环计算 1! + 2! + 3! + ... + 10! 的值(阶乘之和)。 - 编写程序,用嵌套循环打印倒直角三角形(5行,第1行5颗星,第5行1颗星)。
- 编写程序,输入一个正整数,逆序输出它的每一位数字(如输入1234输出4 3 2 1)。