※ 引述《spong (請輸入ID)》之銘言:
: 今天翻書突然看到c++條件運算子的問題
: 像c = a > b ? a : b 我可以理解
: 但當我翻到下一頁,看到以下程式碼
: int main(void)
: {
: const char x[2][20] = {"Jason ","at your service\n"};
: const char *y = "Quillstone";
: for(int i = 0;i<3;i++)
: {
: cout << ((i<2)? !i ? x[i]:y:x[1]);
: }
: return 0;
: }
: 我完全不了解 cout << ((i<2)? !i ? x[i]:y:x[1])這行的運作規則
: 請問要怎麼解釋那段程式呢??
非常建議原 PO 換一本書來學習, 因為這份程式碼沒有任何道理.
即便你弄清楚它的流程, 你也學不到 ?: 的正確用法 (尤其放在迴
圈裡的時候). 首先可以把這份程式碼拿去編譯執行看看:
https://wandbox.org/permlink/CUwEvD5BvPy1aRHb
可以發現輸出是 "Jason Quillstoneat your service", 程式碼裡
的每個字串常數剛好只出現一次, 而仔細看迴圈裡 ?: 用法:
a ? b ? c : d : e
c, d, e 敘述也都剛好各被輸出一次, 你可以用寫死的字串來驗證
看看:
https://wandbox.org/permlink/CQsOUrkN59bBcY6r
那麼從左而右 ?: 裡的敘述基本上可以改寫為:
((i < 2) ? !i ? "Jason " : "Quillstone" : "at your service\n")
(i == 0) (i == 1) (i == 2)
?: 的觀念和 if-else 類似, 搭配迴圈使用的話, 需要先知道索引
值和敘述的對應關係, 然後就是平鋪直敘地把它寫下來:
( i == 0 ? "Jason " // if (i == 0) "Jason "
: i == 1 ? "Quillstone" // else if (i == 1) "Quillstone"
: "at your service\n" // else "at your service\n"
)
然後再把寫死的字串用原本的變數給替換回來:
( i == 0 ? x[0] // it's unnecessary to use x[i] here
: i == 1 ? y
: x[1]
)
寫到這邊就可以結束了, 原本敘述裡 i < 2 就是想涵蓋 i == 0
以及 i == 1 兩種情況, 但後面的 !i 又是在唯二的情況下擇一求
值, 這就是我覺得沒有道理的地方 (多餘的條件引進不必要的複雜
度, 違反 zero-overhead principle).
當要在多種情況擇其一的時候, 需要盡可能地把條件變成具有正交
性的, 不會彼此依賴, 這樣程式碼的結構就會趨於簡單, 而且往後
條件變動的話也不太需要大改. 這題我覺得和加不加括號沒關係,
即使 if-else 擠在同一行也不容易理解.