如果条件A匹配,条件B需要匹配才能执行动作C.
我的问题是:
if (/* condition A */) { if(/* condition B */) { /* do action C */ } else /* ... */ } else { /* do action C */ }
是否可以只写一次行为代码C而不是两次?
如何简化它?
你在这类问题中的第一步总是做一个逻辑表。
A | B | Result ------------------- T | T | do action C T | F | ... F | T | do action C F | F | do action C
一旦你完成了表格,解决scheme就很清楚了。
if (A && !B) { ... } else { do action C }
请注意,这个逻辑虽然较短,但对于未来的程序员来说可能很难维护。
你有两个select:
-
编写一个执行“动作C”的函数。
-
重新排列你的逻辑,以便你没有这么多嵌套的if语句。 问自己什么情况会导致“行为C”发生。 当“条件B”为真或“条件A”为假时,它看起来像是发生了这种情况。 我们可以把它写成“不是A或B”。 将其转换成C代码,我们可以得到
if (!A || B) { action C } else { ... }
为了更多地了解这些expression式,我build议使用“布尔代数”,“谓词逻辑”和“谓词演算”。 这些是深刻的math题目。 你不需要全部学习,只是基本知识。
您还应该了解“短路评估”。 正因为如此,expression式的顺序对于完全复制原始逻辑非常重要。 而B || !A
B || !A
在逻辑上是等价的,使用这个作为条件将执行“行动C”时, B
是真实的,无论A
的价值。
你可以像这样简化语句:
if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments { do C }
否则,把“C”的代码放在一个单独的函数中,然后调用它:
DoActionC() { .... // code for Action C } if (condition A) { if(condition B) { DoActionC(); // call the function } else ... } else { DoActionC(); // call the function }
在模式匹配的语言中,可以用更直接反映QuestionC答案中的真值表的方式来expression解决scheme。
match (a,b) with | (true,false) -> ... | _ -> action c
如果您对语法不熟悉,则每个模式都由|表示 后跟与(a,b)匹配的值,下划线用作通配符表示“任何其他值”。 由于唯一的情况是我们想要做的事情不是行动C是什么时候a是真实的,b是假的,我们明确地说这些值作为第一种模式(真,假),然后做任何应该做的情况下。 在其他所有情况下,我们都要进入“通配符”模式并采取行动c。
问题陈述:
如果条件A匹配,条件B需要匹配才能执行动作C.
描述蕴涵 : A意味着B ,一个逻辑命题相当于!A || B
!A || B
(在其他答案中提到):
bool implies(bool p, bool q) { return !p || q; } if (implies(/* condition A */, /* condition B */)) { /* do action C */ }
呃,这也让我绊倒了,但正如Code-Apprentice所指出的那样,我们保证需要do action C
或者运行嵌套的else
块,因此代码可以简化为:
if (not condition A or condition B) { do action C } else { ... }
这就是我们碰到的三种情况:
- 嵌套的
do action C
在你的问题的逻辑中需要condition A
和condition B
是true
– 在这个逻辑中,如果我们到了if
语句的第二项,那么我们知道condition A
是true
因此我们需要评估是condition B
是true
- 嵌套的
else
块在你的问题的逻辑要求condition A
为true
,condition B
为false
– 我们可以达到这个逻辑的else
块的唯一方法是,如果condition A
为true
,condition B
为false
- 在你的问题逻辑中的外部
else
块要求condition A
是false
– 在这个逻辑中,如果condition A
是假的,我们也do action C
道具Code-Apprentice矫直我在这里。 我build议接受他的答案 ,因为他没有编辑正确提交:/
在逻辑概念中,你可以解决这个问题如下:
f = ab +!a
f =?
作为一个被certificate的问题,这导致f = !a + b
。 有一些方法可以certificate真值表, 卡诺图等问题。
所以在C语言中,你可以使用如下:
if(!a || b) { // Do action C }
PS: 卡诺图也用于更复杂的一系列条件。 这是一种简化布尔代数expression式的方法。
即使已经有了很好的答案,但我认为这种方法对于刚刚接触布尔代数的人来说可能更直观,然后评估一个真值表。
你想要做的第一件事就是看你想要执行的条件C.这是(a & b)
。 另外当!a
所以你有(a & b) | !a
(a & b) | !a
。
如果你想尽量减less你可以继续下去。 就像在“正常”的算术中,你可以乘以。
(a & b) | !a = (a | !a) & (b | !a)
(a & b) | !a = (a | !a) & (b | !a)
。 a | !a总是正确的,所以你可以将它交叉出来,这样就会使结果最小化: b | !a
b | !a
。 如果顺序有差别,因为只有在!a为真时(例如,当!a是一个空指针检查,而b是指针@LordFarquaad指针上的操作时),你才可能检查b要切换两个。
另一种情况(/ * … * /)在c不执行时总是被执行,所以我们可以把它放在else的情况下。
另外值得一提的是,将行动c放入方法可能是有意义的。
这留给我们以下代码:
if (!A || B) { doActionC() // execute method which does action C } else { /* ... */ // what ever happens here, you might want to put it into a method, too. }
这样,您也可以通过更多的操作数来最小化这些操作数,这些操作数很快会被真值表所忽略。 另一个好办法是卡诺图。 但是我现在不会更深入的了解这一点。
为了使代码更像文本,使用布尔标志。 如果逻辑特别模糊,请添加注释。
bool do_action_C; // Determine whether we need to do action C or just do the "..." action // If condition A is matched, condition B needs to be matched in order to do action C if (/* condition A */) { if(/* condition B */) do_action_C = true; // have to do action C because blah else do_action_C = false; // no need to do action C because blarg } else { do_action_C = true; // A is false, so obviously have to do action C } if (do_action_C) { DoActionC(); // call the function } else { ... }
if((A && B ) || !A) { //do C } else if(!B) { //... }
我将提取C到一个方法,然后在所有情况下尽快退出函数。 如果可能的话,最后一个else
子句几乎总是被倒置的。 以下是一步一步的例子:
提取C:
if (A) { if (B) C(); else D(); } else C();
if
要摆脱else
的第一个倒置:
if (!A) { C(); return; } if (B) C(); else D();
摆脱第二点:
if (!A) { C(); return; } if (B) { C(); return; } D();
然后你可以注意到,这两个案件有相同的身体,可以合并:
if (!A || B) { C(); return; } D();
可选的东西要改善将是:
-
取决于上下文,但如果
!A || B
!A || B
是混淆,提取它到一个或多个variables来解释意图 -
无论哪一个
C()
或D()
都是非例外情况都应该最后一个,所以如果D()
是例外,那么if
最后一次倒置
使用标志也可以解决这个问题
int flag = 1; if ( condition A ) { flag = 2; if( condition B ) { flag = 3; } } if(flag != 2) { do action C }