6.6.3 default标号
default标号(default label)提供了相当于else子句的功能.如果所有的case标号与switch表达式的值都不匹配,并且default标号存在,则执行default标号后面的语句.例如,在上述例子中添加一个计数器otherCnt统计读入多少个辅音字母,为switch结构增加default标号,其标志的分支实现otherCnt的自增:
//if ch is a vowel,increment the appropriate counter
switch(ch){
case 'a':
++aCnt;
break;
//remaining vowel cases as before
default:
++otherCnt;
break;
}
在这个版本的代码中,如果ch不是元音,程序流程将执行default标号的相关语句,使otherCnt的值加1.
-----------------------------------------------------我是华丽的分割线-----------------------------------------------------
实践告诉你:哪怕没有语句要在default标号下执行,定义default标号仍然是有用的.定义default标号是为了告诉它的读者,表明这种情况已经考虑到了,只是没什么要执行的.
-----------------------------------------------------我是华丽的分割线------------------------------------------------------
一个标号不能独立存在,它必须位于语句之前.如果switch结构以default标号结束,而且default分支不需要完成任何任务,那么该标号后面必须有一个空语句.
6.6.4 switch表达式与case标号
switch求解的表达式可以非常复杂.特别是,该表达式也可以定义和初始化一个变量:
switch(int ival=get_response())
在这个例子中,ival被初始化为get_response函数的调用结果,其值将要与每个case标号作比较.变量ival始终存在于整个switch语句中,在switch结构外面该变量就不再有效了.
case标号必须是整型常量表达式.例如,下面的标号将导致编译时的错误:
//illegal case label values
case 3.14: //noninteger
case ival: //nonconstant
如果两个case标号具有相同的值,同样也会导致编译时的错误.
6.6.5 switch内部的变量定义
对于switch结构,只能在它的最后一个case标号或default标号后面定义的变量:
case true:
//error:declaration precedes a case label
string file_name=get_file_name();
break;
case false:
//...
制定这个规则是为了避免出现代码跳过变量的定义和初始化的情况.
回顾变量的作用域,变量从它的定义点开始有效,直到它所在块结束为止.现在考虑如果在两个case标号之间定义变量会出现什么情况.该变量会在块结束之前一直存在.对于定义该变量的编号后面的其他case标号,它们所关联的代码都可以使用这个变量.如果switch从那些后续case标号开始执行,那么这个变量可能还未定义就要使用了.
在这种情况下,如果需要为某个特殊的case定义变量,则可以引入块语句,在该块语句中定义变量,从而保证这个变量在使用前被定义和初始化.
case true:
{
//ok:declaration statement within a statement block
string file_name=get_file_name();
//...
}
break;
case false:
//...
习题 6.7 前面已实现的统计元音的程序存在一个问题:不能统计大写的原因字母.编写程序统计大小写的元音,也就是说,你的程序计算出来的aCnt,既包括'a'也包括'A'出现的次数,其他四个元音也一样.
习题 6.8 修改元音统计程序使其可统计出读入的空格、制表符和换行符的个数.
习题 6.9 修改元音统计程序使其可统计以下双字符序列出现的次数:ff、f1以及fi.
习题 6.10 下面每段代码都暴露了一个常见编程错误.请指出并修改之.
a. switch(ival){
case 'a':aCnt++;
case 'e':eCnt++;
default: iouCnt++;
}
b.switch(ival){
case 1:
int ix=get_value();
ivec[ix]=ival;
break;
default:
ix=ivec.size()-1;
ivec[ix]=ival;
}
c.switch(ival){
case 1,3,5,7,9:
oddcnt++;
break;
case 2,4,6,8,10:
evencnt++;
break;
}
d.int ival=512 jval=1024,kval=4096;
int bufsize;
//...
switch(swt){
case ival:
bufsize=ival*sizeof(int);
break;
case jval:
bufsize=jval*sizeof(int);
case kval:
bufsize=kval*sizeof(int);
break;
}