※ 引述《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 挤在同一行也不容易理解.