7.7 多重选择:switch和break
有时程序需要在多个选项中进行选择。可以用if...else if...else来完成。但是,大多数情况下使用switch语句更方便。
如何使用switch语句的例子:
/* animals.c -- uses a switch statement */
#include
#include
int main(void)
{
char ch;
printf("Give me a letter of the alphabet, and I will give ");
printf("an animal name\nbeginning with that letter.\n");
printf("Please type in a letter; type # to end my act.\n");
while ((ch = getchar()) != '#')
{
if('\n' == ch)
continue;
if (islower(ch)) /* lowercase only */
switch (ch)
{
case 'a' :
printf("argali, a wild sheep of Asia\n");
break;
case 'b' :
printf("babirusa, a wild pig of Malay\n");
break;
case 'c' :
printf("coati, racoonlike mammal\n");
break;
case 'd' :
printf("desman, aquatic, molelike critter\n");
break;
case 'e' :
printf("echidna, the spiny anteater\n");
break;
case 'f' :
printf("fisher, brownish marten\n");
break;
default :
printf("That's a stumper!\n");
} /* end of switch */
else
printf("I recognize only lowercase letters.\n");
while (getchar() != '\n')
continue; /* skip rest of input line */
printf("Please type another letter or a #.\n");
} /* while loop end */
printf("Bye!\n");
return 0;
}
/* 输出:
*/
7.7.1 switch语句
要对紧跟在关键字switch后圆括号中的表达式求值。然后程序扫描标签列表,直到发现一个匹配的值为止。然后程序跳转至那一行。如果没有匹配的标签,如果有default:标签行,就跳转至该行;否则,程序继续执行在switch后面的语句。
break让程序离开switch语句,跳至switch语句后面的下一条语句。如果没有break语句,就从匹配标签开始执行到switch末尾。
顺带一提,break语句可用于循环和switch语句中,但是continue只能用于循环中。尽管如此,如果switch语句在一个循环中,continue便可作为switch语句的一部分。这种情况下,就像在其他循环中一样,continue让程序跳出循环的剩余部分,包括switch语句的其他部分。
如果只希望处理某个标签的语句,就必须在switch语句中使用break语句。另外,C语言的case一般都指定一个值,不能使用一个范围。
switch在圆括号中的测试表达式的值应该是一个整数值(包括char类型)。case标签必须是整数类型(包括char类型)的常量或整型常量表达式(即,表达式中只包含整型常量)。不能用变量作为case标签。switch的构造如下:
switch( 整型表达式 ){
case 常量1:
语句 <--可选
case 常量2:
语句 <--可选
default: <--可选
语句 <--可选
}
7.7.2 只读每行的首字符
只读每行的首字符,丢弃一行中其他字符的行为,经常出现在响应单字符的交互程序中。可以用下面的代码实现这样的行为:
while( (getchar()) != '\n' ){
continue; /*跳过输入行的其余部分*/
}
循环从输入中读取字符,包括按下Enter键产生的换行符。注意,函数的返回值并没有赋给ch,以上代码所做的只是读取并丢弃字符。
由于最后丢弃的字符是换行符,所以下一个被读取的字符是下一行的首字符。
假设用户一开始就按下Enter键,那么程序读到的首个字符就是换行符。下面的代码就是处理这种情况:
if( ch == '\n' ){
continue;
}
7.7.3 多重循环
可以在switch语句中使用多重case标签。
// vowels.c -- uses multiple labels
#include
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("Enter some text; enter # to quit.\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;
} // end of switch
} // while loop end
printf("number of vowels: 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;
}
/* 输出:
*/
严格地说,case 'U'的break语句并不需要。因为即使删除这条break语句,程序流会接着执行switch中的下一条语句,即default:break;。
所以,可以把case 'U'd的break语句去掉以缩短代码。但是从另一方面看,保留这条break语句可以防止以后在添加新的case时遗漏break语句。
在该例中,如果使用ctype.h系列的toupper()函数可以避免使用多重标签,在进行测试之前就把字母转换成大写字母。
while( (ch = getchar()) != '#' ){
ch = toupper( ch );
switch( ch ){
case 'A': a_ct++;
break;
case 'E': e_ct++;
break;
case 'I': i_ct++;
break;
case 'O': o_ct++;
break;
case 'U': u_ct++;
break;
default: break;
} //switch结束
} //while循环结束
或者,也可以先不转换ch,把toupper(ch)放进switch的测试条件中:switch(toupper(ch))。
小结:带多重选择的switch语句
一般注解:
程序根据expression的值跳转至相应的case标签处。然后,执行剩下的所有语句,除非执行到break语句进行重定向。
形式:
switch( expression ){
case label1: statement1 //使用break跳出switch
case label2: statement2
default: statement3
}
可以有多个标签语句,default语句可选。
7.7.4 switch和if else
如果是根据浮点类型的变量和表达式来选择,就无法使用switch。如果根据变量在某范围内决定程序流的去向,使用switch就很麻烦。
这种情况用if就很方便。
if( integer < 1000 && integer > 2 )
使用switch要涵盖以上范围,需要为每个整数(3~999)设置case标签。但是,如果使用switch程序通常运行快一些,生成的代码少一些。