if语句

if语句根据特定表达式是否为真来有条件地执行另一个语句.if语句有两种形式:其中一种带else分支而另一种则没有.根据语法结构,最简单的if语句是这样的:

if(condition)
statement

其中的condition部分必须用圆括号括起来.它可以是一个表达式,例如:

if(a+b>c){/*...*/}

或者一个初始化声明,例如:

//ival only accessible within the if statement
if(int ival=compute_value()){/*...*/}

通常,statement部分可以是复合语句,即用花括号括起来的块语句.

如果在条件表达式中定义了变量,那么变量必须初始化.将已初始化的变量值转换为bool值后,该bool值决定了条件是否成立.变量类型可以是任何可转换为bool型的类型,这意味着它可以是算术类型或指针类型.将来会提及:一个类类型能否用在条件表达式中取决于类本身.迄今为止,在所有用过的类类型中,IO类型可以用作条件,但vector类型和string类型一般不可用作条件.

为了说明if语句的用法,下面程序用于寻找vector<int>对象中的最小值,并且记录这个最小值出现的次数.为了解决这个问题,需要两个if语句,

一个判断是否得到一个新的最小值,而另一个则用来增加当前最小值的数目.

if(minVal>ivec[i]){/*process new minVal*/}
if(minVal==ivec[i]){/*process occurrence count*/}

语句块用作if语句的对象

现在单独考虑上述例子中的每个if语句.其中一个if语句将要决定是否出现了一个新的最小值,如果是的话,则要重置计数器并更新最小值:

if(minVal>ivec[i]){//execute both statements if condition is true
minVal=ivec[i];
occurs=1;
}

另一个if语句则有条件地更新计数器,它只需一个语句,因此不必用花括号括起来:

if(minVal==ivec[i])
++occurs;

--------------------------------------------------------------我是充实的分割线----------------------------------------------

小心:当多个语句必须作为单个语句执行时,比较常见的错误是漏掉了花括号

-------------------------------------------------------------我是充实的分割线----------------------------------------------

在下面的程序中,与程序员缩进目的相反,对occurs的赋值并不是if语句的一部分:

//error:missing curly brackets to make a block!
if(minVal>ivec[i])
minVal=ivec[i];
occurs=1; //executed unconditionally:not part of the if

这样写的话,对occurs的赋值将会无条件地执行.这种错误很难发现,因为程序代码看起来是正确的.

-------------------------------------------------------------我是华丽的分割线----------------------------------------------

实践告诉你:很多编辑器和开发环境都提供工具自动根据语句结构缩排源代码.有效地利用这些工具将是一种很好的编程方法.

-------------------------------------------------------------我是华丽的分割线----------------------------------------------

if语句的else分支

紧接着,我们要考虑如何将那些if语句放在一起形成一个执行语句序列.这些if语句的排列顺序非常重要.如果采用下面的顺序:

if (minVal>ivec[i])
{
 minVal=ivec[i];
 occurs=1;
}
//potential error if minVal has just been set to ivec[i]
if(minVal==ivec[i])
++occurs;

那么计数器将永远得不到1.这段代码只是对第一次出现的最小值重复计数.

这样两个if语句不但在值相同时执行起来有潜在的危险,而且还是没必要的.同一个元素不可能既小于minVal又等于它.如果其中一个条件是真的,那么另一个条件就可以安全地忽略掉.if语句为这种只能二选一的(either-or)条件提供了else子句.

if else语句的语法形式为:

if(condition)
 statement1
else
 statement2

如果condition为真,则执行statement1;否则,执行statement2:

if(minVal==ivec[i])
 ++occurs;
else if(minVal>ivec[i]){
 minVal=ivec[i];
 occurs=1;
}

值得注意的是,statement2既可以是任意语句,也可以是花括号括起来的块语句.在这个例子里,statement2本身是一个if语句.

悬垂else

对于if语句的使用,还有一个重要的复杂问题没有考虑.上述例子中,注意到没有一个if分支能直接处理元素值大于minVal的情况.从逻辑上来说,可以忽略这些元素-------如果该元素比当前已找到的最小值大,那就应该没什么要做的.然而,通常需要使用if语句为三种不同情况提供执行的内容,即如果一个值大于、小于或等于其他值时,可能都需要执行特定的步骤.为此重写循环部分,显式地处理这三种情况:

//note:indented to make clear how the else branches align with the corresponding if
if(minVal<ivec[i])
{}  //empty block
else if(minVal==ivec[i])
++occurs;
else{
 minVal=ivec[i];
 occurs=1;
}

上述三路测试精确地控制了所有的情况.然而,简单地把前两个情况用一个嵌套if语句实现将会产生问题:

//oops:incorrect rewrite:This code won't work!
if(minVal<=ivec[i])
 if(minVal==ivec[i])
  ++occurs;
 else{//this else goes with the inner if,not the outer one!
  minVal=ivec[i];
  occurs=1;
 }

----------------------------------------------------------我是华丽的分割线------------------------------------------

小心:这个版本表明了所有语言的if语句都普遍存在着潜在的二义性.这种情况往往称为悬垂else(dangling-else)问题,产生于一个语句包含的if子句多于else子句时:对于每一个else,究竟它们归属于哪个if语句?

---------------------------------------------------------我是华丽的分割线------------------------------------------

在上述的代码中,缩进的用法表明else应该与外层的if子句匹配.然而,C++中悬垂else问题带来的二义性,通过将else匹配给最后出现的尚未匹配的if子句来解决.在这个情况下,这个if else语句实际上等价于下面的程序:

//oops:still wrong,but now the indentation matches execution path
if(minVal<=ivec[i])
//indented to match handling of dangling-else
if(minVal==ivec[i])
++occurs;
else{
 minVal=ivec[i];
 occurs=1;
}

可以通过用花括号将内层的if语句括起来称为复合语句,从而迫使这个else子句与外层的if匹配.

 if(minVal<=ivec[i]){
 if(minVal==ivec[i])
  ++occurs;
}else{
 minVal=ivec[i];
 occurs=1;
}

-----------------------------------------------------------我是华丽的分割线-----------------------------------------------

提示:有些编程风格建议总是在if后面使用花括号.这样做可以避免日后修改代码时产生混乱和错误.至少,无论if(或者while)后面是简单语句,例如赋值和输出语句,还是其他任意语句,使用花括号都是一个比较好的做法.

-----------------------------------------------------------我是华丽的分割线------------------------------------------------

 

习题6.5  改正下列代码:

a.

if(ival1!=ival2)
ival1=ival2
else ival1=ival2=0;

b.

if(ival<minval)
minval=ival;  //remenber new minimum
occurs=1;    //reset occurrence counter

c.

if(int ival=get_value())
cout<<"ival="<<ival<<endl;
if(!ival)
cout<<"ival=0/n";

d.

if(ival=0)
ival=get_value();

 

习题6.6  什么是"悬垂else"?C++是如何匹配else子句的?

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值