4.2.2  表达并列条件选择的switch语句:如果……如果……如果……

在现实世界中,还有这样一类特殊的条件选择:

如果明天是晴天,我就穿T恤;

如果明天是阴天,我就穿衬衣;

如果明天是雨天,我就穿外套。

之所以说这是条件选择,是因为它根据不同的情况执行了不同的动作;而之所以说它特殊,是因为这些不同情况(晴天、阴天、雨天)属于同一条件(天气情况)。只要是条件判断,我们就可以用if语句将其表达出来,利用前面介绍过的if…else if…并列条件选择语句,我们可以将这个看天穿衣的场景表达如下:

// 用并列条件选择实现的看天穿衣
#include <iostream> using namespace std; // 枚举可能的天气情况
enum Weather
{
SUNNY = , // 晴天,指定其值为1
CLOUDY, // 阴天,其值递增为2
RAINY, // 雨天,其值递增为3
}; int main()
{
cout<<"请输入明天的天气(1-晴天;2-阴天;3-雨天):";
int nW = ;
// 获取用户输入天气情况
cin>>nW; // 对天气情况进行判断
if(SUNNY == nW) // 如果是晴天
{
// 输出晴天该穿的衣服
cout<<"晴天穿T恤"<<endl;
}
else if(CLOUDY == nW) // 如果是阴天
{
cout<<"阴天穿衬衣"<<endl;
}
else if(RAINY == nW) // 如果是雨天
{
cout<<"雨天穿外套"<<endl;
}
else
{
cout<<"不知道明天是什么天气,你爱穿什么穿什么吧"<<endl;
} return ;
}

使用并列条件选择语句,虽然能够把这种并列选择场景表达出来,可是我们不得不书写多个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 = ;
cin>>nOrder; // 获取用户选择 switch(nOrder)
{
case : // 将包含case分支放在靠上的位置
cout<<"一对鸡翅"<<endl; // 完成独有的功能
// 注意,这里省略掉了case分支末尾的break关键字
case : // 将被包含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分支。

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

  1. 你好,C++(19)“老师,我这次四级考试过了没有?”——4.2 条件选择语句

    4.2  条件选择语句 “老师,我这次四级考试过了没有?” 如果老师被问到这个问题,他会如何回答?是的,他会根据不同的条件选择不同的回答: 如果考试成绩大于等于60,那就回答:“恭喜你,你通过了这次考 ...

  2. C语言的本质(20)——预处理之二:条件预处理和包含头文件

    我们可以通过定义不同的宏来决定编译程序对哪些代码进行处理.条件编译指令将决定那些代码被编译,而哪些是不被编译的.可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件. 条件编译可分为三种情况,按 ...

  3. 通过实体反射实现CriteriaQuery并列条件查询

    将实体反射之后获取查询字段的值,并添加到Predicate对象数组中 public Predicate getPredicateAnd(T entity, Root<T> root, Cr ...

  4. 你好,C++(22) 排排坐,吃果果——4.3.3 for循环:某个范围内…每个都…

    4.3.3  for循环:某个范围内…每个都… 既然while语句和do…while…语句都已经可以满足我们表达循环现象的需要,那为什么C++还要专门提供for语句来表达循环现象呢?在现实世界中,常常 ...

  5. Google开发规范

    v0.2 - Last updated November 8, 2013 源自 Google's C++ coding style rev. 3.274 目录 由 DocToc生成     头文件   ...

  6. Google's C++ coding style

    v0.2 - Last updated November 8, 2013 源自 Google's C++ coding style rev. 3.274 目录 由 DocToc生成     头文件   ...

  7. python关键字详解

    今天依旧在啃:<笨方法学python>,其中习题37是复习各种关键字.我本想百度一下记一下就ok了,但是百度出来第一个就Hongten的博客.我才意识到我也有博客,我应该学习他,把这些积累 ...

  8. JavaSE学习总结第04天_Java基础语法3

      04.01 选择结构switch语句的格式及其解释 switch语句的格式: switch(表达式) {    case 值1:语句体1;break;    case 值2:语句体2;break; ...

  9. Java-master(github)教材整理

    helloworld class HelloWorld { public static void main(String[] args) { System.out.println("hell ...

随机推荐

  1. Css 八卦

    <div class="box"> <div class="right_d"></div> <span class=& ...

  2. [算法]线段树(IntervalTree)

    转载请注明出处:http://www.cnblogs.com/StartoverX/p/4617963.html 线段树是一颗二叉搜索树,线段树将一个区间划分成一些单元区间,每一个区间对应线段树的一个 ...

  3. EF学习

    一.EF介绍 实体框架 Entity Framework 是ADO.NET 中的一组支持开发面向数据的软件应用程序的技术.在 EF 中的实体数据模型(EDM)由以下三种模型和具有相应文件扩展名的映射文 ...

  4. Reachability 检测网络状态

    -(void)viewWillAppear:(BOOL)animated { [IOSExcept JudgeNetwork];//联网 NSLog(@"检查网络 请稍后....." ...

  5. 转:关于copy_to_user()和copy_from_user()的一些用法

    一.Copy_to_user( to, &from, sizeof(from)) To:用户空间函数  (可以是数组) From:内核空间函数(可以是数组) sizeof(from):内核空间 ...

  6. PHP 类中的常量

    类中的常量与静态成员类似他们只属于类而不属于类的任何实例,访问形式与访问静态成员一样. 例如: <?php class MyConst{ const RED="Red"; c ...

  7. android merge 标签的使用

    <merge xmlns:android="http://schemas.android.com/apk/res/android"> <ToggleButton ...

  8. 【转】android中如何查看某个线程的logcat--不错

    原文网址:http://my.oschina.net/u/236164/blog/51022 单一个项目由很多人开发,然后大家各自打各自的log.到最后logcat就根本没法看了. adb自带的参数里 ...

  9. [又是BUG]常见的RuntimeException

    妈蛋这异常那异常都是异常,不能忍了! 下面总结一些经常遇到的异常(RuntimeExecption):   算术异常类:ArithmeticExecption 数组下标越界异常:ArrayIndexO ...

  10. HDOJ 1397 Goldbach's Conjecture(快速筛选素数法)

    Problem Description Goldbach's Conjecture: For any even number n greater than or equal to 4, there e ...