2008-12-03 142 views
23

这与beautiful code中的一章有关。 在那一章中,我读到了嵌套的ifs。替换嵌套if语句

作者在谈论深度嵌套的ifs作为错误的起源和较少可读性。 他正在讨论用案例陈述和决策表替换嵌套ifs。

任何人都可以说明如何删除案例(选择大小写)和决策表的嵌套ifs吗?

回答

18

好吧,不是直接回答你的问题,因为你具体询问switch/case语句,但是这里有一个类似的问题。

Invert “if” statement to reduce nesting

这谈论更换嵌套如果与后卫语句,即提前返回,而不是逐步解决在返回值之前检查的东西越来越多。

10

一个例子,我总是尝试做的是顶替重嵌套,如果是这样的(实际上这个不是坏,但我看过他们深达8或9级在野外):

if (i == 1) { 
    // action 1 
} else { 
    if (i == 2) { 
     // action 2 
    } else { 
     if (i == 3) { 
      // action 3 
     } else { 
      // action 4 
     } 
    } 
} 

与此:

switch (i) { 
    case 1: 
     // action 1 
     break; 
    case 2: 
     // action 2 
     break; 
    case 3: 
     // action 3 
     break; 
    default: 
     // action 4 
     break; 
} 

我也尽量保持动作尽可能小(函数调用是最适合这个),以保持压缩switch语句(这样你就不必往前走四页到看到它的结尾)。

我相信,决策表只是简单地设置标志,指​​出稍后需要采取什么行动。 “稍后”部分是基于这些标志的动作的简单排序。我可能是错的(它不会是第一次或最后一次:-)。

一个例子是(该标志设置阶段可以如果的是复杂的,因为它的动作是非常简单的):

switch (i) { 
    case 1: 
     outmsg = "no paper"; 
     genmsg = true; 
     mailmsg = true; 
     phonemsg = false; 
     break; 
    case 2: 
     outmsg = "no ink"; 
     genmsg = true; 
     mailmsg = true; 
     phonemsg = false; 
     break; 
    default: 
     outmsg = "unknown problem"; 
     genmsg = true; 
     mailmsg = true; 
     phonemsg = true; 
     break; 
} 

if (genmsg) 
    // Send message to screen. 
if (mailmsg) 
    // Send message to operators email address. 
if (phonemsg) 
    // Hassle operators mobile phone. 
+1

因为“else if”是邪恶的,必须写成“else {if ...}”?但是对于像这样简单的ifs,你是正确的。 – JeeBee 2008-12-03 13:43:11

6

使病情到布尔值,然后写布尔表达式为每一种情况下。

如果代码是:

if (condition1) 
{ 
    do1 
} 
else 
{ 
    if (condition2) 
    { 
     do2 
    } 
    else (condition3) 
    { 
     do3; 

    } 
} 

一个可以写为:

bool cond1=condition1; 
bool cond2=condition2; 
bool cond3=condition3; 

if (cond1) {do1;} 
if (!cond1 and cond2) {do2;} 
if (!cond1 and cond3) {do2;} 
+0

当有很多条件时,这会变得非常难看。另外,可读性会丢失,因为实际条件隐藏在布尔值后面。 – 2012-09-24 20:26:37

+0

@DanielBecroft我实际上看到的是相反的方式。我同意[Jeff Atwood的避免评论的方法],并且为此,您将该布尔变量赋予一个有意义的名称,并且这将*增强*可读性...就这样说,这里介绍的这种方法并不是一个银弹。如果你不想不必要地计算条件会怎样? – Mazyod 2014-07-06 08:19:54

+0

同意@Mazyod上面的缺点是条件得到不必要的计算。在斯卡拉懒惰val帮助那里。 – khivi 2016-03-09 16:06:59

-1

又如一些语言允许这是

  switch true{ 
      case i==0 
       //action 
      break 

      case j==2 
      //action 
      break 

      case i>j 
      //action 
      break 
      } 
8

如何链接IFS?

更换

if (condition1) 
{ 
    do1 
} 
else 
{ 
    if (condition2) 
    { 
     do2 
    } 
    else (condition3) 
    { 
     do3; 

    } 
} 

if (condition1) { 
    do1; 
} else if (condition2) { 
    do2; 
} else if (condition3) { 
    do3; 
} 

这很像复杂条件switch语句。

1

决策表是您在中将条件逻辑存储在数据结构中而不是代码本身中的地方。

所以不是这个(使用@大同的例子):

if (i == 1) { 
    // action 1 
} else { 
    if (i == 2) { 
     // action 2 
    } else { 
     if (i == 3) { 
      // action 3 
     } else { 
      // action 4 
     } 
    } 
} 

你做这样的事情:

void action1() 
{ 
    // action 1 
} 

void action2() 
{ 
    // action 2 
} 

void action3() 
{ 
    // action 3 
} 

void action4() 
{ 
    // action 4 
} 

#define NUM_ACTIONS 4 

// Create array of function pointers for each allowed value of i 
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 } 

// And now in the body of a function somewhere... 
if ((i < NUM_ACTIONS) && actions[i]) 
    actions[i](); 
else 
    action4(); 

如果i的可能性不低编号的整数,那么你可以创建一个查找表而不是直接访问actions数组的i th元素。

当您对几十个可能值做出决定时,该技术比嵌套的if s或switch语句更有用。

0

如果嵌套相当于上述逻辑运算AND

if (condition1) 
{ 
    if (function(2)) 
    { 
     if (condition3) 
     { 
      // do something 
     } 
    } 
} 

等效代码:

if (condition1 && function(2) && condition3) 
{ 
    // do something 
} 

在这两种情况下,当表达式计算假,随后的表达不会被评估。例如,如果condition1为false,则不会调用function(),并且不会评估condition3。

2

例如,一旦验证的一部分失败,您就可以中断。

function validate(){ 
    if(b=="" || b==null){ 
     alert("Please enter your city"); 
     return false; 
    } 

    if(a=="" || a==null){ 
     alert("Please enter your address"); 
     return false; 
    } 
    return true; 
}