4.8 switch语句
在C语言中,switch语句也可以用来从几个选项中选择一个。当基于单个变量或者一个简单表达式(称为控制表达式)的值进行选择时,switch语句特别有用。表达式的值可以是int类型或char类型,但不能是double类型。
例4-20 图4-12的switch语句是实现以下决策表的一种方法。
|
类别标识 |
舰船类别 |
类别标识 |
舰船类别 |
|
B或者b |
战列舰 |
D或者d |
驱逐舰 |
|
C或者c |
巡洋舰 |
F或者f |
护卫舰 |
switch语句显示的消息取决于控制表达式的值,即(char类型)变量class的值。首先对表达式求值;然后搜索case标签列表(case 'B':、case 'b':、case 'C':等)直到找到和控制表达式的值匹配的标签。紧随在匹配的case标签之后的语句被执行。break使程序从switch语句中退出,接着执行switch语句的结束大括号之后的语句。如果没有case标签和switch语句的控制表达式的值匹配,在有default标签的情况下,default标签之后的语句将被执行。如果没有default标签,整个switch语句被跳过。
|
541. switch (class) { 542. case 'B': 543. case 'b': 544. printf("Battleship\n"); 545. break; 546. 547. case 'C': 548. case 'c': 549. printf("Cruiser\n"); 550. break; 551. 552. case 'D': 553. case 'd': 554. printf("Destroyer\n"); 555. break; 556. 557. case 'F': 558. case 'f': 559. printf("Frigate\n"); |
图4-12 具有char类型case标签的switch语句示例
|
560. break; 561. 562. default: 563. printf("Unknown ship class %c\n", class); 564. } |
图4-12(续)
使用“Cruiser”或“Frigate”这样的字符串作为case标签是一种常见的错误。要记住int类型和char类型的值可以作为case标签,但字符串和double类型的值不能作为case标签,另一种常见的错误是忽略了某个选项之后的break语句。在这种情况下,程序执行将“贯穿”到下一个选项。我们在每个break语句之后用一个空行来强调不存在“贯穿”。
忘记switch语句的结束大括号也是经常出现的错误。如果这个大括号丢失并且switch语句具有default标签,紧跟在switch语句之后的其他语句将成为default标签的一部分。
以下的语法展示给出了switch语句作为多选项决策结构的形式。
switch语句
语法: switch (条件表达式){
标签1
语句1
break;
标签2
语句2
break;
.
.
.
标签n
语句n
break;
default:
语句d
}
示例: /* Determine life expectancy of a standard light
bulb */
switch (watts) {
case 25:
life = 2500;
break;
case 40:
case 60:
life = 1000;
break;
case 75:
case 100:
life = 750;
break;
default:
life = 0;
}
说明:控制表达式(即值为int类型或char类型的表达式)被求值并和标签集合中的每一个case标签比较直到找到匹配的标签。标签集合由一个或多个形式为case后紧跟常量值以及一个冒号的标签构成。当找到与控制表达式的值匹配的case标签时,该case标签之后的语句被执行直到遇到break语句。然后switch语句的其余部分被跳过。
注意:case标签之后的语句可以是一条或多条C语句,因此不必用大括号将多条语句构成一个复合语句。如果没有case标签值和控制表达式匹配,整个switch语句被跳过,除非它包含了default标签。如果包含了default标签,default标签之后的语句在没有其他case标签值与控制表达式匹配时执行。
比较嵌套if语句和switch语句
我们可以使用嵌套if语句来实现任何多选项决策,它比switch语句更通用。在语法展示中描述的switch语句在很多情况下更加具有可读性,只要实用就应该使用switch语句。包含double类型或字符串值的case标签是不允许的。
当标签集合包含合理的标签数(最多10个)时应该使用switch语句,但如果值的数量很大,应该使用嵌套if语句。无论switch语句出现在什么地方都应该包含一个default标签。尝试定义default标签的规则有助于考虑当switch语句的控制表达式的值在case标签值集合之外时应该如何处理。
聚焦C语言UNIX连接
作为编写UNIX系统基本组件的语言以及大多数其他操作系统的基础语言,C语言是Ken Thompson和Dennis Ritchie创造的第一个UNIX操作系统开发过程的产物。
在UNIX的开发阶段,它对于使计算机更加易用起了关键作用。直到20世纪20年代末,计算机仍然只是少数组织能够拥有的奢侈品,即使在那时,这些计算机还只是IBM的OS/360这样的单片集成电路系统。直到下一代计算机,即小型计算机出现,时间片共享才使得用户通过终端连接并使用计算机成为可能。这种由UNIX这样的操作系统开创的交互式计算机的使用使计算机更加易于使用。
当Thompson和Ritchie在1969年构建第一个UNIX系统时,他们受到了Multics系统交互的启发,UNIX随后在MIT(作为MIT、通用电气和贝尔实验室的联合项目)被开发出来。1973年,当开发人员重写UNIX内核(即操作系统的心脏)时,他们使用了C语言。从那以后,程序用于从内核请求服务的UNIX系统调用被定义为C函数。这些系统调用的使用使得用C以及后来使用C++编写应用程序非常自然。许多UNIX用户程序也遵循C的语法习惯。
C和UNIX之间的联系是双向的。你将要编写的任何C程序都将显式或隐式调用C库函数。即使是最简单的什么也不做的程序也会隐式调用exit函数,这个函数又调用操作环境来终止程序。其他许多标准C库函数,如getc和time,也需要操作系统的支持,并且这种支持在UNIX上已经成为模式。那些函数的代码涉及请求操作系统的系统服务。虽然存在很多UNIX的特点,但它们都包含一个非常类似C库的“程序员库”。那些函数自身以C接口的形式定义。
另一方面,许多UINX实用程序(包括编程工具)借用了C语法和语义。最好的例子是“shell脚本”工具,通常称为“shell”。一个简单的shell脚本是一个其中包含了准备执行的操作系统命令和一些控制命令执行顺序的逻辑的文本文件。在shell中使用C语法的一个好例子是&&和||运算符的使用。在C语言中,它们完成逻辑表达式的短路求值。在shell中,它们具有类似的行为并能够提供程序的条件执行。对shell表达式a&&b求值,其中a和b是程序,先执行程序a。如果a执行成功,接着执行b;如果a执行失败,b不会被执行。同样,a||b执行a,并且只在a执行失败时执行b。
在计算机界面还是基于文本的时代,C和UNIX之间的联系对于普通用户更加显而易见。图形用户界面的兴起对系统程序员之外的大多数用户隐藏了这些联系。有了图形界面,用户级程序在使用上很少用到语法:大部分输入通过移动并点击鼠标提供而不是输入文本。在许多UNIX实用程序中证明自己的C语法和这些程序没有什么关系。
在UNIX中可用的许多用户级程序现在用Perl、Python和TCL/TK这类语言写成。这些语言通常在更高的、比C更抽象的层面上看待计算机。它们不适合底层编程,例如编写UNIX内核需要的代码,但它们对图形化程序非常适用。
此外,随着几乎普遍使用C和它的后代C++来编写其他操作系统,而且可以使用那些系统的C和C++编译器,人们不再认为C代码是为UNIX环境而编写的。矛盾的是,C和C++作为系统编程语言的普遍性证明了C和UNIX之间联系的一半。所有这些发展的结果是,UNIX和C的联系不再像过去那样明显,虽然这种联系曾经具有重要的历史作用并且对于系统程序员仍然至关重要。
非常感谢Paul Abrahams为这篇文章贡献他对UNIX的真知灼见(Paul Abrahams是Unix for the Impatient的作者以及计算机协会(ACM)的前主席)。
练习
自测
1. 如果color值为'R',那么下面这个随便构造的switch语句会打印出什么?
switch(color){ /*break statements missing */
case 'R':
printf("red\n");
case 'B':
printf("blue\n");
case 'Y':
printf("yellow\n");
}
2. 为什么不能在例4-16和例4-17中使用switch语句重写多选项的if语句代码?
编程
1. 编写一个switch语句,将一个标准灯泡的期望亮度赋给变量lumens,该灯泡的瓦数已存储在watts中。使用下面的表格:
|
瓦 数 |
亮度(单位:流明) |
瓦 数 |
亮度(单位:流明) |
|
15 |
125 |
60 |
880 |
|
25 |
215 |
75 |
1 000 |
|
40 |
500 |
100 |
1 675 |
如果watts值不在表中则给lumens赋值-1。
2. 编写一个与第一个编程练习中描述的switch语句等效的嵌套if语句。







