如果条件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:

  1. 编写一个执行“动作C”的函数。

  2. 重新排列你的逻辑,以便你没有这么多嵌套的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 { ... } 

这就是我们碰到的三种情况:

  1. 嵌套的do action C在你的问题的逻辑中需要condition Acondition Btrue – 在这个逻辑中,如果我们到了if语句的第二项,那么我们知道condition Atrue因此我们需要评估是condition Btrue
  2. 嵌套的else块在你的问题的逻辑要求condition Atruecondition Bfalse – 我们可以达到这个逻辑的else块的唯一方法是,如果condition Atruecondition Bfalse
  3. 在你的问题逻辑中的外部else块要求condition Afalse – 在这个逻辑中,如果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 }