語法書 / AA 競程語法書 下冊 / 第十二單元 / 條件運算子與逗號運算子

12.6 條件運算子與逗號運算子

這一節介紹兩個「別人程式碼裡常見」的運算子。第一個值得學來用,第二個看得懂就好。

條件運算子 a ? b : c

「兩個值選一個」用 if else 寫要四行:

✘ 囉唆寫法:

int mx;
if (x > y) mx = x;
else mx = y;

條件運算子(conditional operator)一行搞定(它收三個運算元,所以也常被叫作「三元運算子」):

✔︎ 省力寫法:

int mx = (x > y ? x : y);

意思是:x > y 成立嗎?成立,整個式子的值就是 x;不成立,就是 y。它是運算式——算出一個值,可以放進任何需要值的地方:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int x = 7, y = 4;

    int mx = (x > y ? x : y);                        // 較大值
    cout << mx << '\n';

    cout << (x % 2 == 0 ? "even" : "odd") << '\n';   // 直接塞進輸出

    int even_cnt = 0, odd_cnt = 0;
    (x % 2 == 0 ? even_cnt : odd_cnt) += 1;          // 特殊用法:挑一個變數來 += 1
    cout << even_cnt << ' ' << odd_cnt << '\n';
    return 0;
}

執行結果:

7
odd
0 1

最後一個用法很妙:?: 選出來的不是值的複本,而是變數本身(可以想成選出一個 12.3 的參考),所以能直接對它 += 1——偶數就加在 even_cnt、奇數就加在 odd_cnt。這種用法有個前提:bc 的型態必須一致。一個 int 一個 long long,編譯器不知道該給你哪種變數,直接編譯錯誤(lvalue required as left operand of assignment)。

也別把它當萬能 if else:分支只能是「一個值」,不能塞好幾個句子;真的要分支做很多事,乖乖用上冊第三單元的 if else。適合它的場合就一種:兩個值選一個——超過這個複雜度,硬塞只會難讀。

逗號運算子:A, B 的結果是 B

逗號也是運算子!A, B 的意思是:先算 A、再算 B,整個式子的結果是 BA 算完就丟)。

int x = (1, 2, 3);      // 先算 1、再算 2、再算 3——x 是 3

-Wall 會對這行警告 left operand of comma operator has no effect——編譯器也覺得你在寫奇怪的東西。)注意宣告裡的逗號不是它:int a, b; 的逗號只是宣告的分隔符(上冊 2.5),沒有「結果是 B」這回事。

它唯一常見的正經出沒地:for 迴圈想一圈同時更新兩個變數。頭尾兩根手指往中間走、把陣列翻面:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a[6] = {1, 2, 3, 4, 5, 6};
    for (int i = 0, j = 5; i < j; i++, j--) {   // i++, j-- 的逗號是逗號運算子
        swap(a[i], a[j]);
    }
    for (int x : a) cout << x << ' ';
    cout << '\n';
    return 0;
}

執行結果:

6 5 4 3 2 1

for 的第三格只能放一個運算式,i++, j-- 用逗號把兩件事併成一件——這是逗號運算子最站得住腳的用法。

動手試試看:寫一支程式讀入 10 個整數,用 (x % 2 == 0 ? even_cnt : odd_cnt) += 1; 一行統計偶數與奇數各幾個。再猜猜 int y = (5, 8); 之後 y 是多少,跑跑看。