! 逻辑非 !expr
< 小于 expr < expr
<= 小于等于 expr <= expr
> 大于 expr > expr
>= 大于等于 expr >= expr
== 相等 expr == expr
!= 不等 expr != expr
&& 逻辑与 expr && expr
|| 逻辑或 expr || expr
关系操作符和逻辑操作符使用算术或指针类型的操作数,并返回bool类型的值.
1.逻辑与、逻辑或操作符
逻辑操作符将其操作数视为条件表达式:首先对操作数求值;若结果为0,则条件为假(false),否则为真(true).仅当逻辑与(&&)操作符的两个操作数都为true,其结果才得true.对于逻辑或(||)操作符,只要两个操作符之一为true,它的值就为true.给定以下形式:
expr1 && expr2 //logical AND
expr1 || expr2 //logical OR
仅当由expr1不能确定表达式的值时,才会求解expr2.也就是说,当且仅当下列情况出现时,必须确保expr2是可以计算的.
a.在逻辑与表达式中,expr1的计算结果为true.如果expr1的值为false,则无论expr2的值是什么,逻辑与表达式的值都为false.当expr1的值为true时,只有expr2的值也是true,逻辑与表达式的值才为true.
b.在逻辑或表达式中,expr1的计算结果为false.如果expr1的值为false,则逻辑或表达式的值取决于expr2的值是否为true.
------------------------------------------------------------我是等待的分割线---------------------------------------------------
注解:逻辑与和逻辑或操作符总是先计算其左操作数,然后再计算其右操作数.只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数.我们常常称这种求职策略为"短路求值(short-circuit evaluation)".
------------------------------------------------------------我也是等待的分割线-----------------------------------------------
对于逻辑与操作符,一个很有价值的用法是:如果某边界条件使expr2的计算变的危险,则应在该条件出现之前,先让expr1的计算结果为false.例如,编写程序使用一个string类型的对象存储一个句子,然后将该句子的第一个单词的个字符全部变成大写,可如下实现:
string s("Expressions in C++ are conposed...");
string::iterator it=s.begin();
//convert first word in s to uppercase
while (it!=s.end()&&!isspace(*it))
{
*it=toupper(*it); //toupper covered in section 3.2.4(章节3.2.4)
++it;
}
在这个例子中,while循环判断了两个条件.首先检查it是否已经到达string类型对象的结尾,如果不是,则it指向s中的一个字符.只有当该检验条件成立时,系统才会计算逻辑与操作符的右操作数,即在保证it确实指向一个真正的字符之后,才检查该字符是否为空格.如果遇到空格,或者s中没有空格而已经到达s的结尾时,循环结束.
2.逻辑非操作符
逻辑非操作符(!)将其操作速汇视为条件表达式,产生与其操作数值相反的条件值.如果其操作数为非零值,则做!操作后的结果为false.例如,可如下在vector类型对象的empty成员函数上使用逻辑非操作符,根据函数返回值判断该对象是否为空:
//assign value of first element in vec to x if there is one
int x=0;
if (!vec.empty())
x=*vec.begin();
如果调用empty函数返回false,则子表达式!vec.empty()的值为true.
3.不应该串接使用关系操作符
关系操作符(<、<=、>、>=)具有左结合特性.事实上,由于关系操作符返回bool类型的结果,因此很少使用其左结合特性.如果把多个关系操作符串接起来使用,结果往往出乎预料:
// oops!this condition does not determine if the 3 values are unequal
if (i<j<k)
{
/*...*/
}
这种写法只要K大于1,上述表达式的值就为true.这是因为第二个小于操作符的左操作数是第一个小于操作符的结果:true或false.也就是,该条件将K与整数0或1作比较.为了实现我们想要的条件检验,应重写上述表达式如下:
if(i<j && j<k){/*...*/}
4.相等测试与bool字面值.
bool类型可转换为任何算术类型-------bool值false用0表示,而true则用1表示.
----------------------------------------------------我是微困的分割线------------------------------------------------
小心:由于true转换为1,因此要检测某值是否与bool字面值true相等,其等效判断条件通常很难正确编写:
if(val==true){/*....*/}
---------------------------------------------------我是微困的分割线-------------------------------------------------
val本身是bool类型,或者val具有可转换为bool类型的数据类型.如果val是bool类型,则该判断条件等效于:
if(val){/*.....*/}
这样的代码更短而且更直接(尽管对初学者来说,这样的缩写可能会令人费解).
更重要的是,如果val不是bool值,val和true的比较等效于:
if(val==1){/*...*/}
这与下面的条件判断完全不同
//condition succeeds if val is any nonzero value
if(val) {/*...*/}
此时,只要val为任意非零值,条件判断都得true.如果显式地书写条件比较,则只有当val等于指定的1值时,条件才成立
习题 5.5 解释逻辑与操作符、逻辑或操作符以及相等操作符的操作数在什么时候计算.
逻辑与、逻辑或操作符采用称为"短路求值"的求值策略,即先计算左操作数,再计算右操作数,且只有当仅靠左操作数的值无法确定该逻辑运算的结果时,才会计算右操作数.
相等操作符的左右操作数均需进行计算
习题5.6 解释下列while循环条件的行为:
char *cp="Hello World";
while(cp && *cp)
该while循环的条件为:当指针cp为非空指针并且cp所指向的字符不为空字符null('.0')时执行循环体.即该循环可以对字符串"Hello World"中的字符进行逐个处理.
习题 5.7 编写while循环条件从标准输入设备读入整型(int)数据,当读入值为42时循环结束.
int val;
while (cin>>val && val!=42)
或者
int val;
cin>>val;
while(val!-42)
习题5.8 编写表达式判断四个值a、b、c和d是否满足a大于b,b大于c,而且c大于d的条件
a>b && b>c && c>d