開啟章節選單
邏輯運算子
極為常見真正APCS考的條件判斷絕對不會這麼單純,通常在同一個 if
裡不會只有一個條件要判斷,比如說:
程式和數學都超電的人往往會被膜拜 Orz
老人、兒童都能折抵票價
沒有錢就買不了新手機 QQ
以上都蘊含「邏輯運算子」的精神,以下就讓我們一起來看看常見的 3 個邏輯運算子!
&& (且,and)
if (條件1 && 條件2) { (敘述1) }
上面那個程式,要條件 1 和條件 2 都滿足才會執行敘述 1,也就是說,只要一個不成立,敘述 1 就不會被執行。
事實上,條件式本身可以被看做一個布林值(所以型態為 bool
的變數其實也可以放進 if
),因此其實 ()
裡裝的是一個布林運算的結果。
以最前面「程式和數學都超電的人往往會被膜拜 Orz」為例:
bool programming_orz, math_orz; ... if (programming_orz && math_orz) { cout << "Orz Orz Orz"; }
在討論這種邏輯運算問題的時候,我們常會畫一個表把 true
和 false
填進去,這就叫做真值表,舉例如下:
x1 | x2 | x1 && x2 |
---|---|---|
1 | 1 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
0 | 0 | 0 |
||(或,or)
if (條件1 || 條件2){ (敘述1) }
和 &&
不同的是,上面那個程式,只要條件 1 和條件 2 滿足其中一個就會執行敘述 1,也就是說,要兩個都不成立,敘述 1 才不會被執行,雖然看起來很簡單,但是將來條件越來越複雜的時候,很常就是因為 &&
和 ||
判斷寫爛了,所以要特別小心。
以「老人、兒童都能折抵票價」為例:
bool is_old, is_child; ... if (is_old || is_child) { cout << "You can get cheaper ticket!"; }
x1 | x2 | x1 || x2 |
---|---|---|
1 | 1 | 1 |
0 | 1 | 1 |
1 | 0 | 1 |
0 | 0 | 0 |
! (不,not)
if (!條件1) { (敘述1) }
!
比較簡潔,只要條件1 是 false
就會執行敘述 1。
以「沒有錢就買不了新手機 QQ」為例:
bool have_money; ... if (!have_money) { cout << "Bye new cellphone..."; }
這個性質可以被運用到前面的 &&
和 ||
。有一個東西叫做「笛摩根定理」,大概是這樣的:
! ( a && b ) = ( !a ) || ( !b )
! ( a || b ) = ( !a ) && ( !b )
當遇到比較複雜的判斷式,可以善用笛摩根定理簡化判斷式,這樣讀code也會比較省力。
x1 | !x1 |
---|---|
1 | 0 |
0 | 1 |
括號與邏輯運算子
在寫程式時,有時候會遇到很複雜的條件判斷,這時候就要善用括號來幫助我們整理程式碼,比如說「高中生或大學生如果是男生就可以參加籃球比賽」:
bool is_high_school_student, is_college_student, is_male; if ((is_high_school_student || is_collge_student) && is_male) { cout << "You can join the basketball game!"; }
當然如果需要的話,也可以套更多層的括號。
陷阱
請看下面這段程式碼:
string s = "abc"; int n; cin >> n; if(s[n] == 'c' || s.length() > n) cout << "OK";
你會發現這個程式如果輸入的 n 是 3,你或許會獲得 RE,這是因為字串 s 的 index 根本就沒有到 3,所以會獲得所謂「undefined behavior」的結果。
undefined behavior 就是指未定義的行為,C++ 不知道到底如何執行,在這種情況下,任何結果都有可能發生,包括程式當掉、輸出奇怪的結果甚至是讓程式永久卡住,所以要特別注意。
解決方法很簡單,只要把條件的順序調換一下就好了:
string s = "abc"; int n; cin >> n; if(s.length() > n || s[n] == 'c') cout << "OK";
這樣 n < 3
時才會判斷第二個條件,這叫做「邏輯短路」,意思是當第一個條件已經可以確定結果時,就不會再去判斷第二個條件,這樣就可以避免 undefined behavior 的問題。
所以,在寫程式時,一定要注意邏輯運算子的順序,這樣才能避免一些不必要的問題。
小測驗
下列哪個敘述是正確的?