第 1 章 循环结构的本质与作用
计算机程序的核心是 “处理数据”,而数据处理中最常见的需求是重复执行相同或类似的操作(例如计算 1 到 100 的和、遍历数组元素、读取文件每一行)。循环结构(Loop)是程序设计中实现 “重复执行” 的核心工具,它通过 “条件判断” 控制代码块的执行次数,避免了重复编写相同代码的冗余。
第 2 章 for
循环:结构化的 “计数循环”
2.1 语法格式
for(初始化表达式; 条件表达式; 步长表达式){
循环体语句;
}
- 初始化表达式:仅在循环开始前执行一次,用于设置循环的初始状态(如定义计数器
int i=0
)。 - 条件表达式:每次循环开始前判断,若为真(非 0)则执行循环体,否则退出循环。
- 步长表达式:每次循环体执行后执行,用于更新循环状态(如
i++
)。
2.2 执行流程
- 执行初始化表达式(仅一次)。
- 判断条件表达式:若为真→执行循环体→执行步长表达式→回到步骤 2;若为假→退出循环。
2.3 经典示例:计算 1 到 100 的和
#include <stdio.h>
int main() {
int sum = 0;
// 初始化i=1;条件i≤100;步长i++
for(int i=1; i<=100; i++){
sum = sum + i; // 循环体:累加i到sum
}
printf("1到100的和是:%d\n", sum); // 输出5050
return 0;
}
2.4 使用场景
- 循环次数明确的场景(如遍历数组、打印 n 行文本)。
- 多变量控制的循环(如同时操作两个计数器):
for(int i=0, j=10; i<j; i++, j--){ // 同时初始化i和j,同时更新 printf("i=%d, j=%d\n", i, j); }
2.5 注意事项
- 初始化表达式可以省略,但需在循环前手动初始化变量(如
int i=0; for(; i<10; i++){...}
)。 - 条件表达式省略时,默认为 “永真”(
for(;;){...}
→死循环)。 - 步长表达式可以写复杂操作(如
i+=2
→每次步长 + 2)。
第 3 章 while
循环:条件驱动的 “不确定循环”
3.1 语法格式
初始化表达式;
while(条件表达式){
循环体语句;
步长表达式; // 通常需要手动更新状态
}
3.2 执行流程
- 执行初始化表达式(在循环外)。
- 判断条件表达式:若为真→执行循环体→回到步骤 2;若为假→退出循环。
3.3 经典示例:用户输入验证
#include <stdio.h>
int main() {
int password;
printf("请输入密码(1234):");
scanf("%d", &password);
// 条件:密码不等于1234时循环
while(password != 1234){
printf("密码错误!重新输入:");
scanf("%d", &password); // 循环体中更新password的值
}
printf("密码正确,登录成功!\n");
return 0;
}
3.4 使用场景
- 循环次数不确定,但终止条件明确的场景(如读取用户输入直到正确、从文件读取数据直到末尾)。
3.5 注意事项
- 必须在循环体内更新条件相关的变量(如示例中的
password
),否则可能导致死循环。 - 与
for
循环可以相互转换(for
更适合已知次数,while
更适合条件驱动)。
第 4 章 do-while
循环:强制优先执行的 “至少一次循环”
4.1 语法格式
初始化表达式;
do{
循环体语句;
步长表达式; // 通常需要手动更新状态
}while(条件表达式); // 注意分号结尾!
4.2 执行流程
- 执行初始化表达式(在循环外)。
- 执行循环体(至少一次)。
- 判断条件表达式:若为真→回到步骤 2;若为假→退出循环。
4.3 经典示例:游戏试玩引导
#include <stdio.h>
int main() {
char playAgain;
do{
printf("正在进行游戏试玩...\n");
printf("是否继续玩?(输入y继续,其他退出):");
scanf(" %c", &playAgain); // 注意空格跳过换行符
}while(playAgain == 'y' || playAgain == 'Y'); // 玩完一次后判断是否继续
printf("游戏结束!\n");
return 0;
}
4.4 使用场景
- 需要至少执行一次循环体的场景(如用户引导、数据校验前的预操作)。
4.5 注意事项
- 循环结束的分号
;
不可省略(否则编译错误)。 - 条件判断在循环体之后,因此即使条件一开始不满足,循环体也会执行一次。
第 5 章 三种循环的对比与选择策略
维度 | for 循环 | while 循环 | do-while 循环 |
---|---|---|---|
执行顺序 | 初始化→条件→循环体→步长 | 条件→循环体(可能不执行) | 循环体→条件(至少执行一次) |
典型场景 | 已知循环次数(如遍历数组) | 未知次数但条件明确(如输入验证) | 必须执行一次(如用户引导) |
死循环风险 | 较低(条件易控制) | 较高(忘记更新条件变量) | 较高(同上) |
第 6 章 循环的高级技巧与常见错误
6.1 嵌套循环:循环内的循环
用于处理二维结构(如矩阵、表格),例如打印乘法表:
#include <stdio.h>
int main() {
for(int i=1; i<=9; i++){ // 外层循环:控制行
for(int j=1; j<=i; j++){ // 内层循环:控制列
printf("%d×%d=%-2d ", j, i, i*j); // 左对齐,占2位
}
printf("\n"); // 每行结束换行
}
return 0;
}
6.2 循环中的break
与continue
break
:直接终止整个循环,跳转到循环后的代码。continue
:跳过当前循环体剩余代码,直接进入下一次循环。
6.3 常见错误
- 死循环:忘记更新循环变量(如
while(i<10){...}
但i
始终不变)。 - 越界访问:循环条件错误导致数组索引超出范围(如
for(int i=0; i<=10; i++)
访问长度为 10 的数组)。 do-while
分号缺失:do{...}while(条件)
后忘记加分号;
,导致编译错误。
第 7 章 实际开发中的循环优化
- 减少循环内计算:将循环内不变的计算移到循环外(如
for(int i=0; i<arr.length; i++)
改为int len=arr.length; for(int i=0; i<len; i++)
)。 - 避免深层嵌套:嵌套超过 3 层会显著降低代码可读性和性能。
- 优先使用
for
循环:在已知次数时,for
的结构更紧凑,便于阅读和维护。
用生活化例子,秒懂三种循环结构
咱们先抛开代码,想象一个生活场景:你需要把 20 个苹果从箱子 A 搬到箱子 B。这个过程需要重复 “搬苹果” 的动作,直到搬完 —— 这就是循环的核心:重复执行相同操作,直到满足某个条件停止。
1. for
循环:按计划搬苹果(最 “省心” 的循环)
场景:你提前数好了箱子 A 有 20 个苹果,计划 “每次搬 1 个,搬 20 次就停”。
对应代码逻辑:
// 初始化:知道要搬20次(i=0);条件:没搬完(i<20);步长:每次搬1个(i++)
for(int i=0; i<20; i++){
搬1个苹果();
}
特点:
- 像 “按计划表做事”:提前定好 “开始(i=0)、结束(i<20)、每一步怎么做(i++)”,循环次数完全确定。
- 最常用在 “已知循环次数” 的场景(比如遍历数组、计算 1 到 100 的和)。
2. while
循环:看条件搬苹果(最 “谨慎” 的循环)
场景:你不知道箱子 A 有多少苹果,但箱子 B 有个 “容量限制”—— 最多只能装 20 个。你每次搬 1 个,搬之前先看箱子 B 有没有装满:没装满就继续搬,装满就停。
对应代码逻辑:
int 已搬数量 = 0;
while(已搬数量 < 20){ // 每次搬之前检查条件:没装满?
搬1个苹果();
已搬数量++;
}
特点:
- 像 “先检查再行动”:每次循环开始前先判断条件,条件满足才执行循环体。
- 适合 “循环次数不确定,但终止条件明确” 的场景(比如用户输入密码,直到输入正确才停止)。
3. do-while
循环:先搬再说(最 “头铁” 的循环)
场景:箱子 B 的容量限制还是 20 个,但你特别着急 —— 不管有没有装满,先搬 1 个再说!搬完后再检查:如果没装满,继续搬;如果装满了,就停。
对应代码逻辑:
int 已搬数量 = 0;
do{
搬1个苹果(); // 先执行一次操作!
已搬数量++;
}while(已搬数量 < 20); // 搬完后检查条件
特点:
- 像 “先做再检查”:至少执行一次循环体(哪怕一开始条件就不满足)。
- 适合 “必须先执行一次操作,再判断是否继续” 的场景(比如游戏中 “先让玩家尝试一次操作,再判断是否继续游戏”)。
总结:三种循环的 “性格” 差异
循环类型 | 执行顺序 | 典型场景 | 最少执行次数 |
---|---|---|---|
for | 先计划,再循环(初始化→条件→循环体→步长) | 已知循环次数(如遍历数组) | 0(条件不满足则不执行) |
while | 先检查,再循环(条件→循环体) | 未知次数但条件明确(如输入验证) | 0(条件不满足则不执行) |
do-while | 先循环,再检查(循环体→条件) | 必须执行一次(如用户引导流程) | 1(至少执行一次) |