C语言小课堂:switch

我们今天来一起学习C语言中的 switch 语句。

  1. 什么是 switch 语句?

在C语言中, switch 语句是一种多分支选择语句,它允许程序根据一个表达式的值,从多个代码块中选择一个来执行。它提供了一种比使用多个 if-else if-else 语句更简洁、更清晰的方式来处理复杂的条件判断,特别是当你有多个可能的值需要判断时。

switch 语句的基本结构如下:

switch (expression) {
case constant_expression_1:
// 当 expression 的值等于 constant_expression_1 时执行的代码
break; // break 语句用于跳出 switch 结构
case constant_expression_2:
// 当 expression 的值等于 constant_expression_2 时执行的代码
break;
// ... 可以有任意数量的 case 分支
default:
// 当 expression 的值与所有 case 都不匹配时执行的代码(可选)
break; // 默认分支中的 break 也是可选的,因为已经是最后一个分支了
}

expression:这是一个整型表达式(可以是 int , char , enum 等类型,但不能是 floatdouble)。 switch 语句会计算这个表达式的值。

case constant_expressioncase 关键字后面跟着一个 常量表达式 (必须是常量,不能是变量或范围)。当 expression 的值与某个 case 后面的 constant_expression 相等时,对应的 case 代码块就会被执行。

break 语句 : 这是 switch 语句中至关重要的一部分!break 语句用于 跳出 switch 结构 。如果没有 break,程序会继续执行下一个 case 的代码,直到遇到 breakswitch 结束,这被称为“ 穿透”(fall-through)。

default 关键字 :这是一个可选的关键字,用于处理 expression 的值与所有 case 都不匹配的情况。如果 default 存在,并且没有 case 匹配成功,那么 default 后面的代码块就会被执行。default 可以放在 switch 块内的任何位置,但通常放在最后。

  1. 何时使用 switch 语句?

当你需要根据一个变量或表达式的特定、离散的整型值来执行不同的操作时,switch 语句是理想的选择。

什么时候用?

当你有多个选项或状态需要根据一个特定的值进行分发时。

例如,根据用户输入的菜单选项执行不同功能。

根据星期几显示不同的日程。

处理状态机的不同状态转换。

为什么用?

代码可读性更高:相比于长串的 if-else if-else 结构,switch 语句在处理多重等值判断时,逻辑结构更清晰,更易于理解和维护。

执行效率可能更高:在某些情况下,编译器可能会优化 switch 语句,使其比一系列 if-else if 链更高效,尤其是在 case 分支数量很多时。

避免“嵌套地狱”:可以有效避免多层 if-else 嵌套带来的复杂性和可读性下降。

和关联知识点的联系和区别(if-else if-else) :

如果你的判断基于一个变量的特定值,并且这些值是离散的整型或字符型,那么 switch 是更好的选择。

如果你的判断涉及范围、不等式、浮点数比较或复杂的逻辑组合,那么 if-else if-else 是唯一或更合适的选择。

if-else if-else:更通用,可以处理任何类型的条件(包括范围、逻辑组合等),灵活性更高。

switch:专门用于处理基于单个整型表达式的等值判断。它不能直接处理浮点数,也不能直接处理复杂的逻辑条件(如 x > 10y == 'A' && z < 5)。

选择依据:

如果你的判断基于一个变量的特定值,并且这些值是离散的整型或字符型,那么 switch 是更好的选择。

如果你的判断涉及范围、不等式、浮点数比较或复杂的逻辑组合,那么 if-else if-else 是唯一或更合适的选择。

在编程学习中的地位和作用:

switch 语句是C语言中控制流的重要组成部分,与 if-else、循环语句( for , while)共同构成了程序的基本执行骨架。

掌握 switch 能够让你编写出更结构化、更高效、更易读的代码,是初学者必须熟练掌握的技能。

  1. 怎么使用 switch 语句?

下面通过几个实际编程场景的例子来演示 switch 语句的用法。

示例一:简易菜单选择器

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>

int main() {
int choice;
printf("请选择一个操作:\n");
printf("1. 加法\n");
printf("2. 减法\n");
printf("3. 乘法\n");
printf("4. 除法\n");
printf("请输入您的选择 (1-4): ");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("您选择了加法操作。\n");
// 在这里添加加法逻辑
break;
case 2:
printf("您选择了减法操作。\n");
// 在这里添加减法逻辑
break;
case 3:
printf("您选择了乘法操作。\n");
// 在这里添加乘法逻辑
break;
case 4:
printf("您选择了除法操作。\n");
// 在这里添加除法逻辑
break;
default:
printf("无效的选择,请输入1到4之间的数字。\n");
break;
}

return 0;
}

解释: 这个例子根据用户输入的整数 choice 来执行不同的操作。如果输入1,执行加法;输入2,执行减法,以此类推。如果输入1-4之外的数字,default 分支会处理无效输入。每个 case 后面的 break 确保了在执行完当前分支后,程序会跳出 switch 语句。

示例二:字符判断

switch 语句也可以用于字符类型,因为字符在C语言中本质上也是整型(ASCII码)。

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
#include <stdio.h>

int main() {
char grade;
printf("请输入您的成绩等级 (A, B, C, D, F): ");
scanf(" %c", &grade); // 注意 %c 前面的空格,用于吸收前一个输入留下的换行符

switch (grade) {
case 'A':
printf("优秀!\n");
break;
case 'B':
printf("良好!\n");
break;
case 'C':
printf("中等!\n");
break;
case 'D':
printf("及格!\n");
break;
case 'F':
printf("不及格!\n");
break;
default:
printf("无效的成绩等级。\n");
break;
}

return 0;
}

解释: 这里根据输入的字符 grade 来判断成绩等级。case 'A': 等价于 case 65:(因为字符 ‘A’ 的ASCII码是65)。

示例三:“穿透”(Fall-through)的利用

虽然通常我们使用 break 来防止穿透,但有时穿透是故意的,可以用来执行多个 case 共享的代码。

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
#include <stdio.h>

int main() {
int month;
printf("请输入月份数字 (1-12): ");
scanf("%d", &month);

printf("这个月有 ");
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
printf("31");
break;
case 4: case 6: case 9: case 11:
printf("30");
break;
case 2:
printf("28或29"); // 简化处理,不考虑闰年
break;
default:
printf("无效的月份");
break;
}
printf(" 天。\n");

return 0;
}

解释: 在这个例子中,多个 case (如 case 1: case 3: ...)后面没有 break,这使得它们会“穿透”到下一个有 breakcase 或者 default。这样,对于所有有31天的月份,它们都共享同一行 printf("31"); 代码,避免了代码重复。

💻 配套习题

第一题 (选择题)

以下关于C语言 switch 语句的描述,哪一项是不正确的?

A. switch 语句中的 expression 可以是 intchar 类型。

B. case 后面的 constant_expression 必须是常量。

C. 如果 switch 语句中没有 break 语句,程序会继续执行下一个 case 的代码。

D. switch 语句能够直接判断浮点数(如 double 类型)的大小范围。

第二题 (填空题)

在C语言的 switch 语句中,如果某个 case 分支的代码执行完毕后,没有遇到 break 语句,程序会继续执行下一个 case 分支的代码,这种现象被称为 ______。

第三题 (代码输出题)

阅读下面的C代码,并写出其输出结果:

#include <stdio.h>
int main() {
int x = 2;
switch (x) {
case 1:
printf("One\n");
case 2:
printf("Two\n");
case 3:
printf("Three\n");
default:
printf("Other\n");
}
return 0;
}

第四题 (概念辨析题)

判断题: default 关键字在 switch 语句中是必须的,否则程序会报错。

A. 正确

B. 错误

第五题 (编程题)

编写一个C程序,模拟一个简单的交通灯系统。程序接收一个字符输入,代表交通灯的颜色(’R’ 代表红灯,’Y’ 代表黄灯,’G’ 代表绿灯)。使用 switch 语句根据输入的颜色输出对应的提示信息:

‘R’:输出 “Stop! Red light.”

‘Y’:输出 “Caution! Yellow light.”

‘G’:输出 “Go! Green light.”

其他输入:输出 “Invalid light color.”

💡 习题讲解

第一题解析

答案:D

A. switch 语句中的 expression 可以是 intchar 类型。

正确。 switch 语句的表达式必须是整型,intchar 都属于整型家族(char 实际上存储的是字符的ASCII码,是整数)。

B. case 后面的 constant_expression 必须是常量。

正确。 case 标签后面只能跟常量值(字面量或用 const 定义的常量),不能是变量。

C. 如果 switch 语句中没有 break 语句,程序会继续执行下一个 case 的代码。

正确。这就是 switch 的“穿透”特性。当一个 case 匹配成功后,如果没有 break,程序会继续执行其后的所有 case(包括 default)的代码,直到遇到 breakswitch 语句结束。

D. switch 语句能够直接判断浮点数(如 double 类型)的大小范围。

不正确。 switch 语句的 expression 必须是整型表达式,不能是 floatdouble 类型。它也无法直接判断大小范围(如 > 10< 5),只能进行精确的等值匹配。判断浮点数范围或不等式通常需要使用 if-else if-else 结构。

第二题解析

答案: 穿透 (或 fall-through)

讲解: 这是一个关键概念。switch 语句的执行机制是,一旦找到匹配的 case ,它会从该 case 开始执行,直到遇到 break 语句或 switch 语句的末尾。如果没有 break,控制流会“穿透”到下一个 case,执行其代码,以此类推。理解这一点对于避免逻辑错误和有时故意利用这一特性(如多个 case 共享代码)非常重要。

第三题解析

答案:

Two
Three
Other

讲解:

程序开始, int x = 2;

switch (x)x 的值为 2

程序查找匹配的 casecase 1: 不匹配。

case 2: 匹配成功。程序开始执行 printf("Two\n");,输出 “Two”。

case 2: 后面 没有 break 语句。因此,程序会继续“穿透”到 case 3:

执行 printf("Three\n");,输出 “Three”。

case 3: 后面 没有 break 语句。程序会继续“穿透”到 default:

执行 printf("Other\n");,输出 “Other”。

default: 后面虽然也没有 break,但它是 switch 的最后一个分支,所以 switch 语句在此结束。

程序返回 0,结束。 这个题目很好地考察了对 switch 语句中 break 作用的理解。

第四题解析

答案: B (错误)

讲解: default 关键字是可选的。它的作用是当 switch 表达式的值与所有 case 标签的值都不匹配时,提供一个备选的执行路径。如果 default 不存在,并且没有 case 匹配成功,那么 switch 语句将不执行任何代码,直接跳过。程序不会因此报错。

第五题解析

答案: 见下方代码及讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

int main() {
char light_color;
printf("请输入交通灯颜色 (R/Y/G): ");
scanf(" %c", &light_color);

switch (light_color) {
case 'R':
printf("Stop! Red light.\n");
break;
case 'Y':
printf("Caution! Yellow light.\n");
break;
case 'G':
printf("Go! Green light.\n");
break;
default:
printf("Invalid light color.\n");
break;
}

return 0;
}

讲解:

包含头文件:#include <stdio.h> 是必需的,因为它包含了 printfscanf 函数的声明。

声明变量:char light_color; 声明一个字符变量来存储用户输入的颜色。

获取用户输入:

printf("请输入交通灯颜色 (R/Y/G): "); 提示用户输入。

scanf(" %c", &light_color); 读取用户输入的字符。注意 %c 前面的空格,这是一个小技巧,用于吸收之前输入操作可能留下的换行符,防止它被 scanf 误读为当前的字符输入。

使用 switch 语句 :

switch (light_color):根据 light_color 的值进行判断。

case 'R': :当 light_color 是字符 ‘R’ 时,执行此分支。printf("Stop! Red light.\n"); 输出对应的提示。

break; :非常重要,确保在执行完当前 case 后跳出 switch 语句,避免“穿透”到其他 case

case 'Y':case 'G': 类似处理。

default: :如果 light_color 不匹配 ‘R’, ‘Y’, ‘G’ 中的任何一个,则执行 default 分支,输出 “Invalid light color.”。 这个编程题考察了 switch 语句的基本结构、字符类型的使用以及 break 语句的正确应用。