c语言小课堂-while语句

1. while语句是什么?

在C语言中,while语句是一种循环控制结构,用于重复执行一段代码,直到指定的条件不再满足为止。它属于“入口条件循环”,这意味着在每次循环迭代之前,都会先检查条件。如果条件为真,则执行循环体;如果条件为假,则跳过循环体并继续执行while语句之后的代码。

基本语法:

1
2
3
while (条件表达式) {
// 循环体(statements to be executed repeatedly)
}
  • 条件表达式:这是一个布尔表达式,其结果为真(非零)或假(零)。
  • 循环体:当条件表达式为真时,这部分代码会被执行。循环体可以是一条语句,也可以是由花括号 {} 包裹的多条语句。

工作原理:

  1. 程序首先评估条件表达式
  2. 如果条件表达式为真(非零),则执行while循环体内的代码。
  3. 循环体执行完毕后,程序再次回到步骤1,重新评估条件表达式
  4. 这个过程会一直重复,直到条件表达式为假(零)时,循环终止,程序继续执行while循环后面的代码。

2. while语句何时用?

while语句在编程中非常常用,尤其适用于以下场景:

  • 当你不确定循环需要执行多少次时:与for循环通常用于已知循环次数的场景不同,while循环更适合那些循环次数取决于某个条件何时变为假的场景。例如,从文件中读取数据直到文件末尾,或者处理用户输入直到输入特定值。
  • 需要根据特定条件重复执行任务时:例如,等待用户输入一个有效值,直到输入正确为止;或者在游戏中,只要玩家生命值大于0就继续游戏。
  • 实现某种状态的持续监控:例如,在一个系统中,持续检查某个标志位是否被设置,一旦设置就执行相应操作。

与关联知识点的联系和区别:

  • for循环的区别

    • for循环通常用于已知循环次数的情况,其结构将初始化、条件和更新表达式集中在一起,更紧凑。
    • while循环更适合未知循环次数的情况,或者当循环的终止条件比较复杂,不适合放在for循环的更新表达式中时。
    • 理论上,任何for循环都可以用while循环实现,反之亦然,但选择哪种循环取决于代码的清晰度和可读性。

    例如:
    for循环:

    1
    2
    3
    for (int i = 0; i < 5; i++) {
    // ...
    }

    等价的while循环:

    1
    2
    3
    4
    5
    int i = 0;
    while (i < 5) {
    // ...
    i++;
    }
  • do-while循环的区别

    • while循环是“入口条件循环”,先判断条件再执行循环体。这意味着如果条件一开始就为假,循环体可能一次都不会执行。
    • do-while循环是“出口条件循环”,它会先执行一次循环体,然后再判断条件。这意味着do-while循环体至少会被执行一次,即使条件一开始就为假。

    例如:
    while循环:

    1
    2
    3
    4
    int x = 10;
    while (x < 5) { // 条件为假,循环体不会执行
    printf("Hello\n");
    }

    do-while循环:

    1
    2
    3
    4
    int x = 10;
    do {
    printf("Hello\n"); // 至少执行一次
    } while (x < 5); // 条件为假,循环在第一次执行后终止

在编程学习中,while语句是掌握程序流程控制的关键部分,它使得程序能够根据动态条件执行重复性任务,是编写交互式程序和处理不确定输入场景的基础。

3. while语句怎么用?

我们通过几个实际编程场景来举例说明while语句的应用。

示例1:计算1到100的和

这个例子虽然也可以用for循环实现,但用while更能体现其基本用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
int sum = 0;
int i = 1; // 初始化计数器

while (i <= 100) { // 条件:i小于等于100
sum += i; // 循环体:累加i
i++; // 更新:i自增
}

printf("1到100的和为:%d\n", sum);
return 0;
}

解释:

  • 我们首先将sum初始化为0,i初始化为1。
  • while (i <= 100)是循环的条件。只要i小于或等于100,循环就会继续。
  • 在循环体内,sum = sum + i 将当前的i值加到sum上。
  • i++i的值增加1。这是非常关键的一步,它确保了i最终会超过100,从而使循环终止。如果忘记这一步,将导致无限循环。

示例2:用户输入验证

要求用户输入一个正数,如果输入非正数,则一直提示重新输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main() {
int num;

printf("请输入一个正整数:");
scanf("%d", &num);

while (num <= 0) { // 条件:如果输入的数非正
printf("输入错误!请重新输入一个正整数:");
scanf("%d", &num);
}

printf("您输入的是:%d\n", num);
return 0;
}

解释:

  • 程序首先提示用户输入一个数。
  • while (num <= 0)是循环条件。只要num小于或等于0(即非正数),就说明输入不符合要求,循环就会继续。
  • 在循环体内,程序会再次提示用户输入,并读取新的值。
  • 当用户最终输入一个正数时,num <= 0的条件变为假,循环终止,程序打印出用户输入的有效数字。

示例3:利用while循环实现菜单选择

创建一个简单的菜单,让用户选择操作,直到用户选择退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>

int main() {
int choice = 0; // 初始化选择,确保第一次进入循环

while (choice != 3) { // 条件:只要选择不是3(退出)就继续
printf("\n--- 菜单 ---\n");
printf("1. 执行操作A\n");
printf("2. 执行操作B\n");
printf("3. 退出\n");
printf("请选择一个选项:");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("您选择了操作A。\n");
// 在这里可以添加操作A的具体代码
break;
case 2:
printf("您选择了操作B。\n");
// 在这里可以添加操作B的具体代码
break;
case 3:
printf("感谢使用,程序退出。\n");
break;
default:
printf("无效的选择,请重新输入。\n");
break;
}
}

return 0;
}

解释:

  • choice变量被初始化为0,确保while (choice != 3)条件在程序开始时为真,从而进入循环。
  • 循环体内,程序显示菜单,并等待用户输入选择。
  • switch语句根据用户的choice执行相应的操作。
  • choice为3时,while (choice != 3)条件变为假,循环终止,程序退出。

通过以上示例,我们可以看到while语句在不同场景下的灵活性和实用性。理解其工作原理和适用场景,是掌握C语言循环控制的关键一步。


配套习题设计

接下来,我们设计5道与while语句相关的习题,难度由易到难递进。

习题1 (选择题):

以下C语言代码段,执行后会输出什么?

1
2
3
4
5
int x = 5;
while (x > 0) {
printf("%d ", x);
x--;
}

A) 5 4 3 2 1 0
B) 5 4 3 2 1
C) 4 3 2 1 0
D) 5 4 3 2 1 -1

习题2 (填空题):

请填写以下代码的空白处,使得程序能够计算并输出从1累加到n(用户输入)的和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
int n, sum = 0, i = 1;
printf("请输入一个正整数n:");
scanf("%d", &n);

while (i <= _____) {
sum += i;
i++;
}
printf("1到%d的和为:%d\n", n, sum);
return 0;
}

习题3 (编程题):

编写一个C语言程序,使用while循环计算并输出一个整数的阶乘。例如,输入5,输出120 (5! = 5 * 4 * 3 * 2 * 1)。如果用户输入负数或0,则提示“请输入一个正整数!”并要求重新输入,直到输入有效为止。

习题4 (选择题):

考虑以下C语言代码:

1
2
3
4
5
6
7
8
9
int count = 0;
int num = 10;
while (num > 0) {
if (num % 2 == 0) {
count++;
}
num--;
}
printf("%d\n", count);

这段代码执行后,count的值是多少?
A) 10
B) 5
C) 0
D) 6

习题5 (编程题):

编写一个C语言程序,模拟一个简单的猜数字游戏。程序随机生成一个1到100之间的整数,然后让用户猜测。

  • 如果用户猜的数字太高,提示“太高了,请再试一次!”
  • 如果用户猜的数字太低,提示“太低了,请再试一次!”
  • 如果用户猜对了,提示“恭喜你,猜对了!你一共猜了X次。”并结束游戏。
    使用while循环来实现游戏的重复猜测过程。

习题讲解

现在,我们来详细讲解上述习题的答案和解题思路。

习题1 (选择题) 答案及解析:

答案:B) 5 4 3 2 1

解析:

  1. int x = 5;:变量x初始化为5。
  2. while (x > 0):进入循环。
    • 第一次迭代:x为5,5 > 0为真。执行printf("%d ", x);输出 5 x--使x变为4。
    • 第二次迭代:x为4,4 > 0为真。执行printf("%d ", x);输出 4 x--使x变为3。
    • 第三次迭代:x为3,3 > 0为真。执行printf("%d ", x);输出 3 x--使x变为2。
    • 第四次迭代:x为2,2 > 0为真。执行printf("%d ", x);输出 2 x--使x变为1。
    • 第五次迭代:x为1,1 > 0为真。执行printf("%d ", x);输出 1 x--使x变为0。
    • 第六次迭代:x为0,0 > 0为假。循环终止。
      因此,最终输出为:5 4 3 2 1

常见错误/易混淆点:

  • 误以为会输出0:循环条件是x > 0,当x变为0时,条件即为假,循环不再执行,所以不会输出0。
  • 误以为会输出-1:同理,循环在x变为0时终止,x不会再递减到-1。

习题2 (填空题) 答案及解析:

答案:n

解析:
这段代码的目标是计算从1累加到n的和。while循环的条件应该确保i从1开始,一直累加到n为止(包括n)。
i等于n时,我们仍然需要执行一次循环体来把n加到sum中。
i增加到n+1时,循环应该终止。
因此,正确的循环条件是i <= n。当i的值小于或等于n时,循环继续。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
int n, sum = 0, i = 1;
printf("请输入一个正整数n:");
scanf("%d", &n);

while (i <= n) { // 填入 n
sum += i;
i++;
}
printf("1到%d的和为:%d\n", n, sum);
return 0;
}

常见错误/易混淆点:

  • i < n:如果条件是i < n,那么当i等于n时,循环就会停止,n本身就不会被加到sum中,导致结果错误。

习题3 (编程题) 答案及解析:

解题思路:

  1. 首先需要一个while循环来处理用户输入,直到输入一个正整数为止。这个循环的条件是输入的数非正。
  2. 一旦获得有效的正整数num,再使用另一个while循环来计算阶乘。
  3. 阶乘的计算:从num开始,每次乘以当前数,然后将当前数减1,直到当前数变为1。

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

int main() {
int num;
long long factorial = 1; // 阶乘结果可能很大,使用long long
int temp_num; // 用于阶乘计算的临时变量

// 循环直到用户输入一个正整数
while (1) { // 使用无限循环,通过break退出
printf("请输入一个正整数(计算阶乘):");
scanf("%d", &num);

if (num > 0) {
break; // 输入有效,退出循环
} else if (num == 0) {
printf("0的阶乘是1。\n"); // 特殊处理0的阶乘
return 0; // 0的阶乘直接输出并退出
} else {
printf("输入错误!请输入一个正整数。\n");
}
}

temp_num = num; // 将有效输入保存到临时变量,避免修改原num
while (temp_num > 0) {
factorial *= temp_num; // 等同于 factorial = factorial * temp_num;
temp_num--;
}

printf("%d的阶乘是:%lld\n", num, factorial);

return 0;
}

解释:

  • 第一个while(1)循环:这是一个无限循环,通过break语句在满足条件时跳出。
    • 它首先读取用户输入。
    • 如果num > 0,说明输入有效,break跳出输入验证循环。
    • 如果num == 0,根据数学定义0的阶乘是1,直接打印并退出程序。
    • 如果num < 0,提示错误,循环继续,要求重新输入。
  • long long factorial = 1;:阶乘增长非常快,所以使用long long类型来存储结果,以防止溢出。
  • temp_num = num;:将用户输入的值复制到temp_num,因为在计算阶乘时temp_num会不断递减,我们希望保留原始的num值用于输出。
  • 第二个while (temp_num > 0)循环:
    • 只要temp_num大于0,就执行循环体。
    • factorial *= temp_num;将当前的temp_num乘到factorial上。
    • temp_num--;temp_num减1,逐步逼近1。
  • temp_num变为0时,循环终止,得到最终的阶乘结果。

常见错误/易混淆点:

  • 阶乘初始值设为0:阶乘的乘法累积,初始值必须是1。
  • 数据类型溢出:对于较大的数(如13的阶乘就已经超出int范围),需要使用long long
  • 无限循环:阶乘计算中忘记temp_num--会导致无限循环。
  • 输入验证不完善:没有处理负数或0的输入。

习题4 (选择题) 答案及解析:

答案:B) 5

解析:

  1. int count = 0;count初始化为0。
  2. int num = 10;num初始化为10。
  3. while (num > 0):进入循环。
    • num = 10: 10 % 2 == 0为真 (count变为1)。num变为9。
    • num = 9: 9 % 2 == 0为假。num变为8。
    • num = 8: 8 % 2 == 0为真 (count变为2)。num变为7。
    • num = 7: 7 % 2 == 0为假。num变为6。
    • num = 6: 6 % 2 == 0为真 (count变为3)。num变为5。
    • num = 5: 5 % 2 == 0为假。num变为4。
    • num = 4: 4 % 2 == 0为真 (count变为4)。num变为3。
    • num = 3: 3 % 2 == 0为假。num变为2。
    • num = 2: 2 % 2 == 0为真 (count变为5)。num变为1。
    • num = 1: 1 % 2 == 0为假。num变为0。
    • num = 0: 0 > 0为假,循环终止。
      最终count的值是5。程序实际上计算的是从1到10之间有多少个偶数。

常见错误/易混淆点:

  • 混淆循环次数与count的最终值:count只在num为偶数时增加。
  • 计算偶数时包含0:本题中num从10递减到1,不包含0。

习题5 (编程题) 答案及解析:

解题思路:

  1. 使用rand()函数生成一个随机数。需要stdlib.htime.h头文件,并用srand(time(NULL))初始化随机数种子。
  2. 使用一个while循环来持续进行猜测,直到用户猜对为止。
  3. 在循环内部,获取用户猜测,并与随机数进行比较,给出相应的提示。
  4. 记录猜测次数。

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <stdlib.h> // 包含rand()和srand()函数
#include <time.h> // 包含time()函数

int main() {
int target_number;
int guess;
int guess_count = 0;
int continue_game = 1; // 控制游戏循环的标志

// 初始化随机数生成器
srand(time(NULL));

// 生成1到100之间的随机数
target_number = (rand() % 100) + 1;

printf("欢迎来到猜数字游戏!\n");
printf("我已经想好了一个1到100之间的数字。\n");

while (continue_game) { // 只要continue_game为真(非0),循环就继续
printf("请输入你的猜测:");
scanf("%d", &guess);
guess_count++; // 每次猜测都增加计数

if (guess > target_number) {
printf("太高了,请再试一次!\n");
} else if (guess < target_number) {
printf("太低了,请再试一次!\n");
} else {
printf("恭喜你,猜对了!你一共猜了%d次。\n", guess_count);
continue_game = 0; // 猜对了,将标志设为0,退出循环
}
}

return 0;
}

解释:

  • #include <stdlib.h>#include <time.h>:用于随机数生成。
  • srand(time(NULL));:使用当前时间作为种子初始化随机数生成器,确保每次运行程序时生成不同的随机数。
  • target_number = (rand() % 100) + 1;:生成1到100之间的随机数。rand() % 100会得到0到99的随机数,加1后变为1到100。
  • int continue_game = 1;:这是一个标志变量,用于控制while循环的执行。当它为1时,循环继续;当它被设置为0时,循环停止。这种方式在不知道循环具体次数时非常有用。
  • while (continue_game):只要continue_game为非零(即1),循环就继续。
  • guess_count++;:每次用户进行猜测,猜测次数就增加。
  • if-else if-else结构:根据用户猜测与目标数字的大小关系给出不同的提示。
  • continue_game = 0;:当用户猜对时,将continue_game设置为0,这将导致while循环的条件在下一次检查时变为假,从而结束游戏。

常见错误/易混淆点:

  • 忘记初始化随机数种子:导致每次运行程序都生成相同的“随机数”。
  • 随机数范围错误:rand() % N生成的是0N-1的数,如果需要1N,则需要 (rand() % N) + 1
  • 无限循环:没有正确设置循环终止条件(例如,猜对后忘记将continue_game设为0)。
  • 没有统计猜测次数。

希望这份详细的讲解和习题能帮助你系统掌握C语言中的while语句!