2012-08-27 165 views
1

我有相当复杂的if语句逻辑。我目前正在使用:C++嵌套如果语句可读性

if(numerical_evaluation) { 

    if ((!boolOne && boolTwo) || !boolThree){ 
     //do stuff 
    } 
} 

其中boolOne,boolTwo和boolThree是逻辑运算(也许x < y或 'myObject-> getBool' 等)。

我不知道一个更好的方法来使这个易于阅读,而不需要在第三个if语句中嵌套||条件。

我有困难的原因是or运算符使得它看起来像第三个if声明可能是有保证的。

一个选择就是做这个。

或者,我可以做类似

if(x <= y) { 

    bool boolFour = false; 
    if ((!boolOne && boolTwo)) 
     boolFour = true; 

    if (boolFour || !boolThree){ 
     //do stuff 
    } 
} 

甚至让一个单独的函数来尝试验证一切,或组合成一个单一的返回值?

或者,我可以尝试以这种方式重组代码,这可能需要大量的时间。

我的问题:什么是格式化复杂if问题的最佳途径 - 这不仅仅包括if (!A && B && C)变化更复杂的评价?当您将||语句与&&语句组合在一行中时,看起来事情变得无望而无法读取(特别是当您对boolOne,boolTwo等进行复杂评估时)。 - Best way to format if statement with multiple conditions也适用同样的原则吗?或者在使用各种逻辑运算符时存在根本差异?

+0

这可能更适合[Programmers.SE](http://programmers.stackexchange.com/)。 – ildjarn

+0

为什么无法读取?这是完全可读的... – ForEveR

+0

这是主观的,可能会被关闭。就我个人而言,我喜欢将逻辑封装到描述函数中,所以最终的陈述就像'if(HasAccess()&& IsEditable()){...'。 – tenfour

回答

13

此:

bool boolFour = false; 
if ((!boolOne && boolTwo)) 
    boolFour = true; 

可以更清楚地表述为:

bool const boolFour = !boolOne && boolTwo; 

通过给boolFour一个良好的,描述性的名称,打破复杂的表达式的这一做法,并命名的子表达式能使代码更具可读性,更容易理解,并且更容易调试。

如果在多个地方使用复杂表达式,则应该使用函数来封装公共逻辑。但是,如果仅在一个地方使用表达式,则最好在本地分解表达式并使用命名的常量变量来保持逻辑与其使用的位置接近。

+3

描述性命名和[德摩根定律](http://en.wikipedia.org/wiki/DeMorgan%27s_Law)的组合可以在表达式的可读性方面创造奇迹。 –

+0

这是一个非常好的方法,出于某种原因,我从来没有想过要这样做。 – enderland

4

编写封装组合布尔检查的帮助函数。 E.G:

bool isEligibleForReduction(int age) { return age < 12 || age >= 60; } 
+0

只是一个脱离主题(和相当无用)评论在这里......为什么不'年龄< 12 || age > 59'或为此'年龄<= 11 ||年龄> = 60'? –

+0

因为我认为在人类语言中规则规定12岁以下的儿童和60岁或以上的成年人有资格获得减免。当然你的建议也是正确的。 – StackedCrooked

+0

是的,这很奇怪,不是吗?为什么不坚持一种比较形式?好吧。 –

0

如果可能的话我通常会做这样的事情:

if(numerical_evaluation) { 

    meaningful_name = (!boolOne && boolTwo); 
    other_meaningful_name = !boolThree; 
    if (meaningful_name || other_meaningful_name){ 
     //do stuff 
    } 
} 
0
if (!numerical_evaluation) { 
    // nothing to do. 
} else if (!boolOne && boolTwo || !boolThree) { 
    // do whatever 
} 

当然,正如其他人所说,boolOneboolTwoboolThree是不是非常有帮助的名字。

0

最好的方法是善用白色空间。

if(numerical_evaluation && 
    (
     (!boolOne && boolTwo) || 
     !boolThree 
    ) 
) { 
     //do stuff 
} 

这不完全漂亮,但它很容易遵循。你也可以使用一个函数来隐藏if逻辑。

bool my_test(int numerical_evaluation, bool boolOne, bool boolTwo, bool boolThree) { 
    return 
     numerical_evaluation && 
     (
      (!boolOne && boolTwo) || 
      !boolThree 
     ); 
} 

if(my_test(numerical_evaluation, boolOne, boolTwo, boolThree)) { 
    // do stuff 
} 

记住,当它不是一个简单的情况下,使用注释给人们你在测试什么(不需要征求意见,只是解释C++语法)的想法。即使他们可以阅读你的if逻辑,但它可以让他们仔细检查它。良好的评论可以快速给人们一个概述你的程序和大部分的逻辑,而不用读取不必要的细节或任何代码。

+2

哦,我的。不不不。这不是更好。我很高兴能够维护一个5,000行的源文件,这个文件大量使用了这种复杂的“格式良好”表达式,这是一场灾难。几乎不可能调试。一旦你有两到三个操作员混合级别,就很难跟踪哪些操作员使用哪些操作数。只需将表达式分解为代表每个子表达式的多个有名的变量。这样的代码是自我记录,更容易调试,更容易理解。 –

+0

该方法已被建议。它不适用于布尔代数和逻辑简化,这可能导致糟糕代码的噩梦,荒谬地将太多的子表达存储到变量中。使用网络系统时,我并不总是喜欢使用这些变量。我想将此添加到对话中。这需要一点练习,但是如果名字很好,我可以更轻松地阅读它。当我不做管理工作时,我个人保留了大约50,000行C++代码,并且在性能情况下我只使用额外的变量。我的Oracle漏洞比我的多了10000倍。 – jbo5112

0

尽管这是一个性能建议,但复杂的布尔表达式有时可以更好地表示为表查找。

复杂的东西,如:

if((a && !c) || (a && b && c)) 
{ 
    category = 1; 
} 
else if((b && !a) || (a && c && !b) 
{ 
    category = 2; 
} 
else if(c && !a && !b) 
{ 
    category = 3; 
} 
else 
{ 
    category = 0; 
} 

变为:

static int categoryTable[2][2][2] = { 
    // !b!c !bc b!c bc 
    0,   3,  2,  2,  // !a 
    1,   2,  1,  1  // a 
}; 
... 
category = categoryTable[a][b][c]; 

代码完成2页614 & 615, “代表复杂的表达式查找”。