邏輯操作符和關係操作符
< 小於 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