首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3.2   决策

C++为做出决策(making decisions)提供了三种主要机制:if-else、switch以及一个通常被称为条件操作符或三元操作符的特殊操作符(因为它是C++中唯一接受三个操作数的操作符)。

3.2.1   if-else语句

不仅所有主要的计算机语言都拥有这样的结构,而且几乎普遍地使用相同的单词。然而,请仔细阅读,因为C++和你当前使用的语言之间可能存在差异。

语言注解:Python程序员尤其需要小心,因为C++不使用缩排作为语法元素。那些习惯了Pascal等语言的人需要注意,C++限制if和else只能控制“单条语句”,当然,这个语句通常是一个复合语句。复合语句是通过把一条或多条简单语句,放到由一对匹配的花括号定义的语句块内创建而成的。

在C++中if-else语句的形式是:

布尔表达式(Boolean-expression)可以是任何东西,只要其求得的值可隐式地转换为一个bool值即可,包括所有基础类型和所有指针类型。任何基础类型的零值都被视为false,所有其他值均被视为true。对于指针来说,除了一个称为null指针(不指向任何东西的指针)的特殊值被视为false外,其余所有值都被视为true(当我们探讨指针的细节时再详加叙述)。

动作(action)必须为单个语句。然而,在C++中,任何包围在一对花括号内的语句组都算单个复合语句。简单语句以一个;(分号)结束,而复合语句则以结束花括号结束。当心,不要在复合语句(有时称为语句块)的结束花括号后加上分号,因为那将构成一条空的简单语句,它的存在也许会“有意义”。举个例子,

在外层由两条语句组成:一条复合语句,其本身由三条语句构成,后面跟着一条空的简单语句。

if-else的else子句是可选的(迄今为止我们尚未在任何程序中使用它)。不过,它必须是受if控制的语句的下一句。比方说,

很好,就像

在上面的代码中,我将受if控制的单个语句写成一个复合语句。下面的if-else语句同样OK:

然而,下面这个就有问题了(看看你能否发现关键的区别):

在这种情况下,编译器也许能够诊断出问题(在复合语句结束处有个多余的分号),但若情况更复杂,if里面又嵌套有if,编译器可能就做不到了。它将会误解你的意图,不会认为else部分与紧靠前面的if有关系。

实   验

编写一个简单的程序,请求用户输入一个整数值,如果所给的值是0就输出简单的消息“zero”,否则输出“not zero”。

3.2.2   switch语句

if-else语句用于进行存在两种可能性的决策(two-way decisions),但有时我们希望进行多种可能性的决策(multi-way decision)。我的意思是有时在逻辑上存在不止两种选择。C++为这种情况提供了switch语句。以下是switch语句的形式:

在使用C++的switch语句时,由许多重要的细节需要注意。

控制表达式求得的必须是某种整型值,或者是可隐式转换为整型的值。所有基础类型都符合这个要求。然而指针不符合此要求,因为不存在从指针类型到整型的自动转换。

case值必须是编译器所知道的固定值。通常来说,这意味着它们应该是某一种基础整型的字面量。稍后我们会发现还存在一些别的选项。

最后的default子句(实际上,如果想标新立异,你可以把它放在选择列表中的任何位置)是可选的,如果缺少它,编译器将你的代码视为默认动作啥也不做。

程序将从相应的case开始执行代码并继续,直到它遇见return语句、break语句,或者switch语句的结束花括号为止。明白这一点很重要,因为具有类似结构的其他语言将下一个case视为当前这个case的结束标志。

语言注解:Pascal是一个为多可能性选择结构使用了不同设计语言的例子。C++特性(跟C家族的其他语言共享,如Java)允许一个case一路执行到底,也就是执行随后的一些case代码,直到某样东西显式地结束连续的执行动作为止。这是导致程序出现bug的原因之一,当使用switch语句的时候你需要小心谨慎,避免简单地将其视作你已经在其他语言中用过的机制在C++中的等价物。

这里有一个简短的代码片断,示范了switch语句的用法:

实   验

编写一个简短的程序,使用以上代码片断,并检查遗漏一个break语句的后果。别忘了向你的程序中添加输入验证。

3.2.3   switch续

下面是使用了switch语句的另外一个代码片断:

注意C++的case机制是如何允许一块代码处理数种情况(cases)的。某些语言以不同的方式处理这种情况,C++则使用了C机制(以便更多的C代码可以作为C++来编译)。

实      验

利用以上代码编写一个程序。然后改进它,以处理大写字母。我们需要做更多的工作,以便从其他可能的输入中挑选出辅音。如果考虑重音字母的情况,那么需要做更多的工作。如果你想进一步体验,<cctype>头提供了大量的来自C标准库的函数,允许你对char进行分类。这些函数包括std::isdigit()、std::ispunct()和std::isalpha()。如果字符分别表示数字、标点符号或字母,则这些函数返回true。欲知更多的细节,以及依赖于现场(locale)的替代品的细节(考虑到各国的字符集),请查阅一份优秀的库参考,例如Nicolai Josuttis的《The C++ Standard Library》[Josuttis 1999]。

3.2.4   条件操作符

C++提供了一种操作符,允许你在两个候选表达式中选择一个来求值,具体选择哪一个则依赖于控制表达式的布尔值。因为它是操作符,所以使用时将会产生一个结果值。正是此值的存在,得以将条件操作符与if-else结构区分开来。下面是条件操作符的形式:

Boolean-control-expression ? result-expression-one : result-expression-two

条件操作符是多种由两个彼此分开的符号构成的C++操作符之一。在这种情况下,两个符号分别是? 和:。首先求得控制表达式的值,以决定应该对两个结果表达式中的哪一个进行求值。如果控制表达式值为true,则整个表达式的值就是第一个结果表达式的求值结果。如果控制表达式的值为false,则整个表达式的值就是第二个结果表达式的值。如果求值存在副作用,则只有对控制表达式进行求值的副作用,以及对被选中的结果表达式进行求值的副作用,才会发生。

语言注解:C程序员应当特别小心,因为C++扩展了这个操作符的潜在用途,所以,例如:

可以编译并工作(它将i和j中较小的那个设置为0)。更有争议的是,以下代码在C++中可以编译:

换句话说,两个备选项都提供相同类型(在本例中大概是int)的对象,位于圆括号中的条件表达式可以出现在赋值的左侧。对这个设施的使用通常是一个糟糕的主意。

这里有一小段代码,示范了条件操作符的一个简单用途(假设count表示橘子的个数):

它为处理单个对象提供了一个恰当的版本,甚至还考虑了英文将零个对象视为复数的怪癖(注意操作符优先规则使得count == 1和count != 1周围的圆括号成为多余。我之所以使用圆括号,纯粹是为了便于你阅读代码)。

实   验

回到numbers程序(第42页),并且:

1. 将通过return 0包含了一个出口的if语句改为if-else语句,以处理两种备选情况。

2. 修改输出语句,以处理用户在以-999结束程序之前只输入了一个值的情况。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论