while循环与do-while循环 | While and Do-While Loops
一、回顾与引入
在上一章中,我们学习了for循环:
for循环的三要素:初始化、条件判断、更新操作for循环的执行流程和常见用法- 嵌套循环和循环变量的作用域
for循环非常适合已知循环次数的情况,比如打印1到100的数字、计算阶乘等。但在实际编程中,我们经常遇到不知道要循环多少次的情况。
想象以下场景:
- 不断询问用户输入,直到用户输入正确为止
- 读取文件内容,直到文件结束
- 游戏中的主循环,直到玩家选择退出
- 计算某个数值,直到达到指定精度
在这些情况下,我们很难预先知道需要循环多少次,而是需要根据某个条件是否满足来决定是否继续循环。
今天我们要学习while循环和do-while循环,它们更适合处理"不知道具体循环次数,但知道循环条件"的情况。
二、while循环详解
1. while循环的基本语法
while (条件表达式) {
// 循环体:需要重复执行的代码
}
和for循环类似,while循环也具有初始化、条件判断、更新操作这些概念,它们在while循环中的写法和位置有所不同。我们下面对它们做出说明:
语法说明:
- 条件表达式:每次循环前都会检查,为真继续循环,为假结束循环
- 循环体:当条件为真时重复执行的代码块
- 没有固定的初始化和更新操作:这些需要我们根据具体情况来编写
2. while循环的执行流程
让我们通过一个简单例子来理解while循环:
int count = 1;
while (count <= 5) {
printf("第%d次循环\n", count);
count++;
}
执行流程:
- 检查条件:count(现在是1) <= 5 吗?答案是"是"
- 执行循环体:打印"第1次循环",然后count变成2
- 重复检查条件:count(现在是2) <= 5 吗?答案是"是"
- 继续执行:直到count变成6时,条件(6 <= 5)为假,循环结束
关键特点:while循环是"先判断,后执行"
3. 简单示例:数字累加
//While_Sum.c
#include <stdio.h>
int main() {
int sum = 0;
int num = 1;
printf("计算1+2+3+...+10的和\n");
while (num <= 10) {
sum += num;
printf("当前累加: %d, 总和: %d\n", num, sum);
num++; // 重要:更新循环变量
}
printf("最终结果: %d\n", sum);
return 0;
}
运行结果:
计算1+2+3+...+10的和
当前累加: 1, 总和: 1
当前累加: 2, 总和: 3
当前累加: 3, 总和: 6
...
当前累加: 10, 总和: 55
最终结果: 55
三、while vs for:何时使用哪种循环?
同样是具有循环变量、初始化、条件判断、更新操作的结构,直观上看,for循环的写法是固定在for(...;...;...) {...}的语句中,写法好像更格式化一些。相比之下,while循环像是一个“手搓”的散装循环,写法没那么标准,但也因之带来了使用上的自由。
这两种循环都各有什么特点呢?
1. for循环适合的场景
- 已知循环次数:比如处理数组、打印图案
- 有规律的计数:比如i从1到100,每次加1
// 打印1到10:用for更合适
for (int i = 1; i <= 10; i++) {
printf("%d ", i);
}
2. while循环适合的场景
- 不知道具体循环次数:基于条件判断
- 条件比较复杂:不仅仅是简单的计数
// 用户输入验证:用while更合适
int age;
printf("请输入年龄(1-150): ");
scanf("%d", &age);
while (age < 1 || age > 150) {
printf("输入无效,请重新输入(1-150): ");
scanf("%d", &age);
}
3. 对比示例:相同功能的不同实现
//Loop_Comparison.c
#include <stdio.h>
int main() {
printf("=== 使用for循环打印1到5 ===\n");
for (int i = 1; i <= 5; i++) {
printf("for: %d\n", i);
}
printf("\n=== 使用while循环打印1到5 ===\n");
int j = 1; // 手动初始化
while (j <= 5) {
printf("while: %d\n", j);
j++; // 手动更新
}
return 0;
}
四、while循环的实际应用
我们仍然通过几个例子加深对while循环的理解:
1. 用户输入验证
这是while循环最常见的用途之一:
//Input_Validation.c
#include <stdio.h>
int main() {
int password;
int correct_password = 1234;
printf("=== 密码验证系统 ===\n");
printf("请输入密码: ");
scanf("%d", &password);
while (password != correct_password) {
printf("密码错误,请重新输入: ");
scanf("%d", &password);
}
printf("密码正确,欢迎使用!\n");
return 0;
/* 这个循环的逻辑流程是:
1. 用户首次输入密码
2. while检查:密码是否错误?
- 如果错误:提示重新输入,获取新密码,继续检查
- 如果正确:退出循环,显示欢迎信息
*/
}
在这个例子里,程序首先通过scanf()语句要求用户输入密码,存储在变量password中。
接着程序进入while循环,程序会首先检查密码是否不等于正确密码1234。如果密码错误,就进入循环体:提示用户重新输入并读取新的密码值。循环体执行结束后,while进行下一次判断:如果密码仍不正确,则继续重复循环。
只有当用户输入正确密码时,循环条件变为假,程序结束循环并继续执行后续语句,显示欢迎信息。
2. 数字游戏:猜数字
//Guess_Number.c
#include <stdio.h>
int main() {
int secret_number = 42; // 假设答案是42
int guess;
int attempts = 0;
printf("=== 猜数字游戏 ===\n");
printf("我想了一个1到100之间的数字,你能猜中吗?\n");
printf("请输入你的猜测: ");
scanf("%d", &guess);
attempts++;
while (guess != secret_number) {
if (guess > secret_number) {
printf("太大了!再试一次: ");
} else {
printf("太小了!再试一次: ");
}
scanf("%d", &guess);
attempts++;
}
printf("恭喜你!答案就是%d\n", secret_number);
printf("你总共猜了%d次\n", attempts);
return 0;
}
3. 菜单循环
在这个例子中,综合运用了我们前几节学过的输入输出、表达式、if判断语句和本节讲的while循环,是综合性较强的例子。你能看懂每一条语句在执行什么样的功能么?
//Menu_System.c
#include <stdio.h>
int main() {
int choice;
printf("=== 简单计算器 ===\n");
while (1) { // 无限循环,直到用户选择退出
printf("\n请选择操作:\n");
printf("1. 加法\n");
printf("2. 减法\n");
printf("3. 乘法\n");
printf("4. 除法\n");
printf("0. 退出\n");
printf("您的选择: ");
scanf("%d", &choice);
if (choice == 0) {
printf("谢谢使用,再见!\n");
break;
// 这是break语句,用于跳出循环。
// 我们接下来就会详细讲解它。
} else if (choice >= 1 && choice <= 4) {
float a, b, result;
printf("请输入两个数: ");
scanf("%f %f", &a, &b);
if (choice == 1) {
result = a + b;
printf("%.2f + %.2f = %.2f\n", a, b, result);
} else if (choice == 2) {
result = a - b;
printf("%.2f - %.2f = %.2f\n", a, b, result);
} else if (choice == 3) {
result = a * b;
printf("%.2f × %.2f = %.2f\n", a, b, result);
} else if (choice == 4) {
if (b != 0) {
result = a / b;
printf("%.2f ÷ %.2f = %.2f\n", a, b, result);
} else {
printf("错误:除数不能为0\n");
}
}
} else {
printf("无效选择,请重新选择\n");
}
}
return 0;
}
五、do-while循环详解
while循环还有一种变体,是do-while循环。它的基本语法如下:
1. do-while循环的基本语法
do {
// 循环体:需要重复执行的代码
} while (条件表达式);
注意:do-while语句最后的分号不能忘记!
2. do-while vs while的区别
那么do-while循环有什么特征呢?它和while循环有什么区别呢?
这两种循环的根本区别在于条件检查的时机。while循环是"先检查后执行"的策略,而do-while循环是"先执行后检查"的策略。
-
执行次数差异:
- while循环:如果初始条件为假,循环体可能一次都不执行
- do-while循环:无论初始条件如何,循环体至少执行一次
-
适用场景:
- while循环:适用于可能不需要执行的重复操作,如文件读取、用户输入验证等
- do-while循环:适用于至少需要执行一次的操作,如菜单显示、游戏主循环等
-
语法细节:
- while循环:条件在循环开始处,没有分号
- do-while循环:条件在循环结束处,必须有分号
让我们通过一个具体例子来看看这种差异:
//DoWhile_vs_While.c
#include <stdio.h>
int main() {
int x = 10;
printf("=== while循环测试 ===\n");
while (x < 5) {
printf("while: x = %d\n", x);
x++;
}
printf("while循环结束,x = %d\n", x);
printf("\n=== do-while循环测试 ===\n");
x = 10; // 重置x的值
do {
printf("do-while: x = %d\n", x);
x++;
} while (x < 5);
printf("do-while循环结束,x = %d\n", x);
return 0;
}
// 实际运行对比:
// while循环:条件不满足 → 跳过循环体 → 直接到后续代码
// do-while循环:执行循环体 → 检查条件不满足 → 到后续代码
运行结果:
=== while循环测试 ===
while循环结束,x = 10
=== do-while循环测试 ===
do-while: x = 10
do-while循环结束,x = 11
在这个例子里,尽管两种情况x都为10,均不满足x < 5的循环条件,但由于do-while循环“先执行再判断”的性质,循环体仍然执行了一次,输出do-while: x = 10并执行x++。
因此:while循环的循环体没有执行,只输出了后续的while循环结束,x = 10;而do-while循环执行了一次,输出了
do-while: x = 10
do-while循环结束,x = 11
3. do-while的典型应用场景
最适合"至少要执行一次"的情况:
//DoWhile_Menu.c
#include <stdio.h>
int main() {
char continue_choice;
printf("=== 欢迎使用程序 ===\n");
do {
printf("\n正在执行程序主要功能...\n");
printf("功能执行完毕!\n");
printf("是否继续使用?(y/n): ");
scanf(" %c", &continue_choice);
} while (continue_choice == 'y' || continue_choice == 'Y');
printf("谢谢使用,再见!\n");
return 0;
}
这个例子完美展现了do-while的优势:
- 程序至少要运行一次主要功能
- 然后询问用户是否继续
- 如果用户选择继续,就重复执行
六、循环控制语句
1. break语句
break用于立即跳出循环,不管条件是否还满足:
//Break_Example.c
#include <stdio.h>
int main() {
int num;
printf("请输入正数(输入0或负数结束):\n");
while (1) { // 无限循环
printf("输入数字: ");
scanf("%d", &num);
if (num <= 0) {
printf("输入了非正数,结束程序\n");
break; // 跳出循环
}
printf("你输入的正数是: %d\n", num);
}
printf("程序结束\n");
return 0;
}
2. continue语句
continue用于跳过本次循环的剩余部分,直接进入下一次循环:
//Continue_Example.c
#include <stdio.h>
int main() {
int i = 0;
printf("打印1到10中的奇数:\n");
while (i < 10) {
i++;
if (i % 2 == 0) {
continue; // 跳过偶数,继续下一次循环
}
printf("奇数: %d\n", i);
}
return 0;
}
运行结果:
打印1到10中的奇数:
奇数: 1
奇数: 3
奇数: 5
奇数: 7
奇数: 9
七、常见错误与注意事项
1. 忘记更新循环变量(死循环)
// ❌ 错误:忘记更新循环变量
int i = 1;
while (i <= 5) {
printf("%d\n", i);
// 忘记写 i++,导致死循环
}
// ✅ 正确:
int i = 1;
while (i <= 5) {
printf("%d\n", i);
i++; // 必须更新循环变量
}
2. do-while忘记分号
// ❌ 错误:缺少分号
do {
printf("执行一次\n");
} while (0) // 缺少分号
// ✅ 正确:
do {
printf("执行一次\n");
} while (0); // 注意分号
3. 条件表达式错误
// ❌ 错误:条件永远为真
int x = 1;
while (x >= 1) { // x永远 >= 1
printf("%d\n", x);
x++; // x会无限增长
}
// ✅ 正确:设定合理的终止条件
int x = 1;
while (x <= 10) { // x最大到10
printf("%d\n", x);
x++;
}
八、三种循环的总结对比
| 循环类型 | 适用场景 | 执行特点 | 典型用法 |
|---|---|---|---|
for |
已知循环次数 | 先判断后执行 | 计数循环、数组遍历 |
while |
未知循环次数 | 先判断后执行 | 条件循环、输入验证 |
do-while |
至少执行一次 | 先执行后判断 | 菜单系统、用户确认 |
选择循环类型的建议
// 1. 明确知道循环次数 → 用for
for (int i = 0; i < 100; i++) {
// 处理100个元素
}
// 2. 基于条件判断,可能一次都不执行 → 用while
while (input != target_value) {
// 直到输入正确值
}
// 3. 至少要执行一次 → 用do-while
do {
// 显示菜单并获取用户选择
} while (user_wants_continue);
九、综合示例:学生成绩统计系统
让我们用一个完整的程序来练习while循环的使用,你能看懂每一条语句在执行什么样的功能么?
//Grade_System.c
#include <stdio.h>
int main() {
float score;
float sum = 0;
int count = 0;
float max_score = 0;
float min_score = 100;
char continue_input;
printf("=== 学生成绩录入系统 ===\n");
printf("请输入学生成绩(0-100),输入-1结束录入\n");
do {
printf("请输入第%d个学生的成绩: ", count + 1);
scanf("%f", &score);
// 检查是否结束输入
if (score == -1) {
break;
}
// 验证成绩范围
if (score < 0 || score > 100) {
printf("成绩无效,请输入0-100之间的数值\n");
continue; // 跳过本次循环,重新输入
}
// 更新统计数据
sum += score;
count++;
// 更新最高分和最低分
if (count == 1) { // 第一个有效成绩
max_score = min_score = score;
} else {
if (score > max_score) {
max_score = score;
}
if (score < min_score) {
min_score = score;
}
}
printf("已录入%d个成绩\n", count);
} while (1); // 无限循环,直到输入-1
// 显示统计结果
if (count > 0) {
printf("\n=== 统计结果 ===\n");
printf("总共录入: %d个成绩\n", count);
printf("总分: %.2f\n", sum);
printf("平均分: %.2f\n", sum / count);
printf("最高分: %.2f\n", max_score);
printf("最低分: %.2f\n", min_score);
// 统计各等级人数
int excellent = 0, good = 0, pass = 0, fail = 0;
printf("\n请重新输入所有成绩以进行等级统计:\n");
for (int i = 0; i < count; i++) {
printf("请输入第%d个成绩: ", i + 1);
scanf("%f", &score);
if (score >= 90) excellent++;
else if (score >= 80) good++;
else if (score >= 60) pass++;
else fail++;
}
printf("\n=== 等级分布 ===\n");
printf("优秀(90-100): %d人\n", excellent);
printf("良好(80-89): %d人\n", good);
printf("及格(60-79): %d人\n", pass);
printf("不及格(0-59): %d人\n", fail);
} else {
printf("没有录入任何有效成绩\n");
}
return 0;
}
十、动手练习
练习1:质数判断器
编写程序判断用户输入的数字是否为质数。质数是只能被1和自己整除的大于1的自然数。
// 参考答案框架
#include <stdio.h>
int main() {
int num, i;
int is_prime = 1; // 假设是质数
printf("请输入一个大于1的整数: ");
scanf("%d", &num);
if (num <= 1) {
printf("%d不是质数\n", num);
return 0;
}
// 用while循环检查是否有除1和自己以外的因子
i = 2;
while (i * i <= num) { // 只需检查到sqrt(num)
if (num % i == 0) {
is_prime = 0; // 找到因子,不是质数
break;
}
i++;
}
if (is_prime) {
printf("%d是质数\n", num);
} else {
printf("%d不是质数\n", num);
}
return 0;
}
练习2:数字倒序输出
编写程序将用户输入的整数倒序输出。
例如:输入1234,输出4321
练习3:银行取款机模拟
编写一个简单的ATM取款机程序:
- 初始余额1000元
- 用户可以查询余额、取款、存款
- 取款时要检查余额是否足够
- 提供退出选项
下一章预告: 学会了所有基本的循环结构后,我们将学习数组,让程序能够处理大量的相同类型数据,为编写更复杂的程序打下基础!



Comments | NOTHING