4.2.2 表达并列条件选择的switch语句:如果……如果……如果……
在现实世界中,还有这样一类特殊的条件选择:
如果明天是晴天,我就穿T恤;
如果明天是阴天,我就穿衬衣;
如果明天是雨天,我就穿外套。
之所以说这是条件选择,是因为它根据不同的情况执行了不同的动作;而之所以说它特殊,是因为这些不同情况(晴天、阴天、雨天)属于同一条件(天气情况)。只要是条件判断,我们就可以用if语句将其表达出来,利用前面介绍过的if…else if…并列条件选择语句,我们可以将这个看天穿衣的场景表达如下:
// 用并列条件选择实现的看天穿衣 #include <iostream> using namespace std; // 枚举可能的天气情况 enum Weather { SUNNY = 1, // 晴天,指定其值为1 CLOUDY, // 阴天,其值递增为2 RAINY, // 雨天,其值递增为3 }; int main() { cout<<"请输入明天的天气(1-晴天;2-阴天;3-雨天):"; int nW = 0; // 获取用户输入天气情况 cin>>nW; // 对天气情况进行判断 if(SUNNY == nW) // 如果是晴天 { // 输出晴天该穿的衣服 cout<<"晴天穿T恤"<<endl; } else if(CLOUDY == nW) // 如果是阴天 { cout<<"阴天穿衬衣"<<endl; } else if(RAINY == nW) // 如果是雨天 { cout<<"雨天穿外套"<<endl; } else { cout<<"不知道明天是什么天气,你爱穿什么穿什么吧"<<endl; } return 0; }
使用并列条件选择语句,虽然能够把这种并列选择场景表达出来,可是我们不得不书写多个if…else if…分支,要书写多个相似的条件表达式,显得有些繁琐。为了简化代码,同时为了使这种并列条件选择表达得更加清晰,C++提供了专门的switch语句以代替复杂的并列条件选择语句,其语法格式如下:
switch( 条件量 ) { case 常量值1: { 语句1; } break; case 常量值2: { 语句2; } break; //… case 常量值n: { 语句n; } break; default: { 默认语句; } }
其中,条件量就是要进行判断的条件,它可以是某个变量,比如,我们这里表示天气状况的nW变量,也可以是某个更加复杂的表达式。而多个常量值就是这个条件量可能的取值,比如,我们这里的条件量nW的可能取值就是SUNNY(晴天)、CLOUDLY(阴天)或者RAINY(雨天)。在执行的时候,switch语句会首先计算条件量的值,然后将这个值按照从上到下的顺序依次与各个case分支的常量值进行比较。如果两者相等,则进入相应case分支执行,直到遇到分支中的break关键字,结束整个switch语句的执行;如果两者不相等,则继续向下判断后面的case分支。如果直到最后都没有遇到与条件量相等的常量值,则进入表示默认情况的default分支开始执行最终完成整个switch语句。default分支表示对所有不符合case分支条件的例外情况的默认处理,它是可选的,如果我不需要处理例外情况,就可以省略掉default分支。如果没有default分支,而同时又找不到匹配的case分支时,程序则不执行任何语句而直接结束switch语句,如图4-2所示。
图4-2 switch语句的执行流程
有了switch语句,我们就可以用它替换if…else if…并列条件选择语句,将“看天穿衣”的并列条件选择简化为:
// 用switch语句实现的并列条件选择 // 以表示天气状况的nW作为条件量,根据不同的天气穿不同的衣服 switch(nW) { case SUNNY: // 以表示晴天的SUNNY作为常量值,进行对晴天状况的处理 cout<<"晴天穿T恤"<<endl; break;// 完成对晴天状况的处理,用break结束整个switch语句 case CLOUDY: // 处理阴天 cout<<"阴天穿衬衣"<<endl; break; case RAINY: // 处理雨天 cout<<"雨天穿外套"<<endl; break; default:// 对例外情况进行默认的处理 cout<<"不知道这是什么天气,你爱穿什么穿什么吧"<<endl; }
在这里,我们用表示天气状况的变量nW作为条件量,而用标识各种天气状况的枚举值作为各个case分支的常量值。在执行的时候,switch语句会将保存了天气状况的条件量nW从上往下地与各个case分支的常量值进行相等比较,也就相当于并列条件选择语句中的“if(SUNNY == nW)”这样的条件判断。这种相等比较从上到下依次进行,直到遇到两者相等的分支,则进入执行,随后遇到break关键字而结束整个switch语句的执行。这样,switch语句实现的逻辑判断跟之前用if…else if…并列条件选择语句实现的完全一致,而代码却更加简洁,而且各种情况用case分支单独列出,逻辑也更加清晰。所以,在表达这种针对同一条件不同情况的条件选择时,我们应该优先选择使用switch语句。
在使用switch语句时需要特别注意的是每个case分支末尾的break关键字。它的作用是跳(break)出当前的case分支,结束整个switch语句的执行。在上面的例子中,如果用户输入的nW是1,表示明天是晴天。因为SUNNY分支的值跟nW相等,那么switch语句会进入“case SUNNY”分支执行,输出:
晴天穿T恤
接着遇到break关键字,就会忽略掉后面的其他case分支而直接结束整个switch语句的执行。而如果这里没有break关键字,它就会继续向下执行后继的case分支,直到遇到break关键字或者是其后的所有分支执行完毕。所以,如果这个switch语句中缺少了break关键字, 那么用户输入1,输出就成了:
晴天穿T恤
阴天穿衬衣
雨天穿外套
不知道这是什么天气,你爱穿什么穿什么吧
看看,整个都乱套了!所以,在使用switch语句时,一定要注意在每个case分支末尾加上break关键字,表示这个分支处理完毕,结束整个switch语句的执行。
当然,事无绝对。大多数时候,我们需要在每个case分支后加上break关键字,而在某些特殊情况下,也就是多个case分支有共同的功能需要完成时,一个case分支功能是另外一个case分支功能的一部分,两个case分支有包含与被包含的关系,这时也可以有意地去掉包含分支中的break关键字,并将其放在靠上的位置,从而达到共用被包含分支中实现公共功能的代码。例如,我们在KFC点餐时,有汉堡套餐和鸡翅套餐可供选择。汉堡套餐就是一个汉堡而已,而鸡翅套餐是在汉堡套餐的基础上再加一对鸡翅而成。在这个场景下,两个case分支(汉堡套餐和鸡翅套餐)就有了公共功能(一个汉堡),而且两者形成了包含与被包含的关系(鸡翅套餐包含汉堡套餐,而汉堡套餐被鸡翅套餐包含),在这种情况下,就可以省略掉包含case分支(鸡翅套餐)的break关键字,并将其放在相对靠上的位置,以实现共用公共功能:
cout<<"请选择您需要的套餐(1-汉堡套餐;2-鸡翅套餐)"<<endl; int nOrder = 0; cin>>nOrder; // 获取用户选择 switch(nOrder) { case 2: // 将包含case分支放在靠上的位置 cout<<"一对鸡翅"<<endl; // 完成独有的功能 // 注意,这里省略掉了case分支末尾的break关键字 case 1: // 将被包含case分支置于靠下的位置 cout<<"一个汉堡"<<endl; // 完成公共功能 break; // 保留break关键字,结束switch语句 default: cout<<"无法识别的选项,请重新选择"<<endl; }
在这个例子中,我们就有意地省略掉了第一个case分支的break关键字,当我们输入1表示选择汉堡套餐时,switch语句会进入“case 1”分支执行,输出“一个汉堡”后,遇到末尾的break关键字,从而结束整个switch语句的执行。最终,我们得到的汉堡套餐的内容是:
一个汉堡
而当我们输入2表示选择鸡翅套餐时 ,switch语句会首先进入“case 2”分支执行,输出“一对鸡翅”后,因为这里没有break关键字,所以它会继续向下进入“case 1”分支执行,输出“一个汉堡”,这时它才遇到break关键字,结束整个switch语句的执行。最终,我们得到的鸡翅套餐的内容是:
一对鸡翅
一个汉堡
这里虽然我们省略了某些case分支末尾的break关键字,但不仅没有造成逻辑上的错误,反而达到了共用公共功能代码的效果。
在使用switch语句时,还需要注意以下几个问题:
(1) switch关键字后括号中的条件量必须是整型的数值变量或表达式,或者是能够被转换为整型的其他类型,比如字符类型或者枚举类型等。
(2) 因为switch之后的条件量是整型,为了与之比较,所以case之后的常量值也必须是整型。它通常是一些表示各种情况的枚举值,比如上面例子中的SUNNY、CLOUDLY等,也可以直接是常量数字,如上面例子中表示选项的常量数字1和2,甚至可以是只有常量参与运算的常量表达式。
(3) 各个case分支的常量值不能相等,即不能出现两个相同条件的case分支。
原文地址:http://www.cnblogs.com/nihaoCPP/p/4101270.html