34

这与漂亮代码中的一章有关。在那一章中,我读到了嵌套if的 s。

作者说的是深度嵌套if的 s 是 bug 的始作俑者,可读性较差。他正在谈论用语句和决策表if替换嵌套的 s 。case

任何人都可以说明如何使用( ) 和决策表删除嵌套if的 s吗?caseselect case

4

11 回答 11

27

好吧,因为您专门询问 switch/case 语句,所以不能直接回答您的问题,但这里有一个类似的问题。

反转“if”语句以减少嵌套

这讨论了用早期返回的保护语句替换嵌套的 if,而不是在确定返回值之前逐步检查越来越多的东西。

于 2008-12-03T13:13:44.380 回答
12

我总是尝试做的一个例子是替换大量嵌套的 if 是这样的(实际上这个还不错,但我已经看到它们在野外达到 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.
于 2008-12-03T13:31:00.430 回答
8

链式ifs怎么样?

代替

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

    }
}

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

这很像复杂条件的 switch 语句。

于 2008-12-03T13:46:19.417 回答
7

将条件转换为布尔值,然后为每种情况编写布尔表达式。

如果代码是:

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;}
于 2008-12-03T13:36:57.190 回答
3

对于决策表,请参阅我对这个问题的回答,或者最好还是阅读Code Complete 2中的第 18 章。

于 2008-12-03T13:57:52.357 回答
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;
}
于 2015-05-16T11:34:18.673 回答
1

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

所以代替这个(使用@Pax的例子):

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不是低编号整数,那么您可以创建一个查找表,而不是直接访问数组的i第 th 个元素。actions

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

于 2008-12-03T14:19:19.210 回答
0

if 和 switch 语句不是纯粹的 OO。它们是条件程序逻辑,但做得非常好!如果您想删除这些语句以获得更多面向对象的方法,请结合“状态”和“描述符”模式

于 2008-12-03T13:58:28.377 回答
0

您也可以考虑使用访问者模式

于 2008-12-03T14:15:24.193 回答
0

嵌套 if 等价于逻辑运算符 AND

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

等效代码:

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

在这两种情况下,当表达式计算结果为 false 时,不会计算后续表达式。例如,如果 condition1 为 false,则不会调用 function(),也不会评估 condition3。

于 2013-10-03T10:43:53.783 回答
-1

一些语言允许的另一个例子是这个

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

            case j==2
             //action
            break

            case i>j
             //action
            break
           }
于 2008-12-03T13:39:24.173 回答