C语言学习栏目目录
目录
源码
使用条件运算符和 if else 语句很容易编写二选一的程序。然而,有时程序需要在多个选项中进行选择。可以用if else if...else来完成。但是,大多数情况下使用switch语句更方便。下程序清单演示了如何使用switch语句。该程序读入一个字母,然后打印出与该字母开头的动物名。
/************************************************************************
功能: 使用switch语句
/************************************************************************/
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
printf("给我字母表中的一个字母,我就给一个以这个字母开头的动物名字\n");
printf("请给出开头,输入 # 结束!\n");
while ((ch = getchar()) != '#')
{
if ('\n' == ch)
continue;
if (islower(ch)) //只接受小写字母
switch (ch)
{
case 'a':
printf("argali,亚洲的一种野生绵羊\n");
break;
case 'b':
printf("babirusa, 东南亚疣猪,一种马来西亚野猪\n");
break;
case 'c':
printf("coati, 科提,类浣熊的哺乳动物\n");
break;
case 'd':
printf("desman, 德斯曼,水生,鼹鼠状生物\n");
break;
case 'e':
printf("echidna, 针鼹,刺食蚁兽\n");
break;
case 'f':
printf("fisher,费舍尔,棕色貂\n");
break;
default:
printf("未完,待续!\n");
} // switch结束
else
printf("只能小写字母有效.\n");
while (getchar() != '\n')
continue; //跳过输入行的剩余部分
printf("请输入字母开头或者 #.\n");
} // while循环结束
printf("再见!\n");
return 0;
}
篇幅有限,我们只编到f,后面的字母以此类推。在进一步解释该程序之前,先看看输出示例:
给我字母表中的一个字母,我就给一个以这个字母开头的动物名字
请给出开头,输入 # 结束!
a
argali,亚洲的一种野生绵羊
请输入字母开头或者 #.
e
echidna, 针鼹,刺食蚁兽
请输入字母开头或者 #.
b
babirusa, 东南亚疣猪,一种马来西亚野猪
请输入字母开头或者 #.
g
未完,待续!
请输入字母开头或者 #.
#
再见!
该程序的两个主要特点是:使用了switch语句和它对输出的处理。我们先分析switch的工作原理。
1、switch语句
要对紧跟在关键字 switch 后圆括号中的表达式求值。在上程序清单中,该表达式是刚输入给 ch的值。然后程序扫描标签(这里指,case 'a' :、case 'b' :等)列表,直到发现一个匹配的值为止。然后程序跳转至那一行。如果没有匹配的标签怎么办?如果有default :标签行,就跳转至该行;否则,程序继续执行在switch后面的语句。
break语句在其中起什么作用?它让程序离开switch语句,跳至switch语句后面的下一条语句(见下图)。如果没有break语句,就会从匹配标签开始执行到switch末尾。例如,如果删除该程序中的所有break语句,运行程序后输入d,其交互的输出结果如下
给我字母表中的一个字母,我就给一个以这个字母开头的动物名字
请给出开头,输入 # 结束!
d
desman, 德斯曼,水生,鼹鼠状生物
echidna, 针鼹,刺食蚁兽
fisher,费舍尔,棕色貂
未完,待续!
请输入字母开头或者 #.
#
再见!
如上所示,执行了从case 'd':到switch语句末尾的所有语句。
顺带一提,break语句可用于循环和switch语句中,但是continue只能用于循环中。尽管如此,如果switch语句在一个循环中,continue便可作为switch语句的一部分。这种情况下,就像在其他循环中一样,continue让程序跳出循环的剩余部分,包括switch语句的其他部分。C语言的case一般都指定一个值,不能使用一个范围。
switch在圆括号中的测试表达式的值应该是一个整数值(包括char类型)。case标签必须是整数类型(包括char类型)的常量或整型常量表达式(即,表达式中只包含整型常量)。不能用变量作为case标签。switch的构造如下:
switch ( 整型表达式)
{
case 常量1:
语句 <--可选
case 常量2:
语句 <--可选
default : <--可选
语句 <--可选
}
2、只读每行的首字符
上程序清单的另一个独特之处是它读取输入的方式。运行程序时读者可能注意到了,当输入dab时,只处理了第1个字符。这种丢弃一行中其他字符的行为,经常出现在响应单字符的交互程序中。可以用下面的代码实现这样的行为:
while (getchar() != '\n')
continue; //跳过输入行的其余部分
循环从输入中读取字符,包括按下Enter键产生的换行符。注意,函数的返回值并没有赋给ch,以上代码所做的只是读取并丢弃字符。由于最后丢弃的字符是换行符,所以下一个被读取的字符是下一行的首字母。在外层的while循环中,getchar()读取首字母并赋给ch。
假设用户一开始就按下Enter键,那么程序读到的首个字符就是换行符。下面的代码处理这种情况:
if (ch == '\n')
continue;
3、多重标签
如下程序清单:
/************************************************************************
功能:可以在switch语句中使用多重case标签
/************************************************************************/
#include <stdio.h>
int main(void)
{
char ch;
int a_ct, e_ct, i_ct, o_ct, u_ct;
a_ct = e_ct = i_ct = o_ct = u_ct = 0;
printf("输入一些字母; 输入#退出 .\n");
while ((ch = getchar()) != '#')
{
switch (ch)
{
case 'a':
case 'A':
a_ct++;
break;
case 'e':
case 'E':
e_ct++;
break;
case 'i':
case 'I':
i_ct++;
break;
case 'o':
case 'O':
o_ct++;
break;
case 'u':
case 'U':
u_ct++;
break;
default:
break;
} // switch结束
} // while循环结束
printf("元音数个数: A E I O U\n");
printf(" %4d %4d %4d %4d %4d\n",a_ct, e_ct, i_ct, o_ct, u_ct);
return 0;
}
假设如果ch是字母i,switch语句会定位到标签为case 'i' :的位置。由于该标签没有关联break语句,所以程序流直接执行下一条语句,即i_ct++;。如果 ch是字母I,程序流会直接定位到case 'I' :。本质上,两个标签都指的是相同的语句。
严格地说,case 'U'的 break 语句并不需要。因为即使删除这条 break 语句,程序流会接着执行switch中的下一条语句,即default : break;。所以,可以把case 'U'的break语句去掉以缩短代码。但是从另一方面看,保留这条break语句可以防止以后在添加新的case(例如,把y作为元音)时遗漏break语句。
下面是该程序的运行示例:
输入一些字母; 输入#退出 .
hello world
#
元音数个数: A E I O U
0 1 0 2 0
小结:带多重选择的switch语句
关键字:switch
一般注解:
程序根据expression的值跳转至相应的case标签处。然后,执行剩下的所有语句,除非执行到break语句进行重定向。expression和case标签都必须是整数值(包括char类型),标签必须是常量或完全由常量组成的表达式。如果没有case标签与expression的值匹配,控制则转至标有default的语句(如果有的话);否则,将转至执行紧跟在switch语句后面的语句。
形式:
switch ( expression )
{
case label1 : statement1//使用break跳出switch
case label2 : statement2
default : statement3
}
可以有多个标签语句,default语句可选。如果choice的值是1或2,打印第1条消息;如果choice的值是3,打印第2
条和第3条消息(程序继续执行后续的语句,因为case 3后面没有break语句);如果choice的值是4,则打印第3条消息;如果choice的值是其他值只打印最后一条消息。
4、switch和if else
何时使用switch?何时使用if else?你经常会别无选择。如果是根据浮点类型的变量或表达式来选择,就无法使用 switch。如果根据变量在某范围内决定程序流的去向,使用 switch 就很麻烦,这种情况用if就很方便:
if (integer < 1000 && integer > 2)
使用switch要涵盖以上范围,需要为每个整数(3~999)设置case标签。但是,如果使用switch,程序通常运行快一些,生成的代码少一些。