你好,C++(20).4.2.2 表达并列条件选择的switch语句:如果……如果……如果……

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分支。

原文地址:https://www.cnblogs.com/nihaoCPP/p/switch.html