假设我有这样的伪代码:

bool conditionA = executeStepA();
if (conditionA){
    bool conditionB = executeStepB();
    if (conditionB){
        bool conditionC = executeStepC();
        if (conditionC){
            ...
        }
    }
}

executeThisFunctionInAnyCase();

函数executeStepX当且仅当前一个成功时执行。 在任何情况下,executeThisFunctionInAnyCase函数都应该在最后被调用。 我在编程方面是一个新手,所以很抱歉提出一个非常基本的问题:有没有一种方法(例如在C/ c++中)以代码易读性为代价,避免长if链产生那种“金字塔式代码”?

我知道如果我们可以跳过executeThisFunctionInAnyCase函数调用,代码可以简化为:

bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;

但是约束是executeThisFunctionInAnyCase函数调用。 break语句可以以某种方式使用吗?


当前回答

给定函数:

string trySomething ()
{
    if (condition_1)
    {
        do_1();
        ..
            if (condition_k)
            {
                do_K();

                return doSomething();
            }
            else
            {
                return "Error k";
            }
        ..
    }
    else
    {
        return "Error 1";
    }
}

我们可以通过反转验证过程来摆脱语法嵌套:

string trySomething ()
{
    if (!condition_1)
    {
        return "Error 1";
    }

    do_1();

    ..

    if (!condition_k)
    {
        return "Error k";
    }

    do_K();

    return doSomething ();
}

其他回答

你可以使用&&(逻辑与):

if (executeStepA() && executeStepB() && executeStepC()){
    ...
}
executeThisFunctionInAnyCase();

这将满足你的两个要求:

executeStep<X>()应该只在前一个成功时才计算(这称为短路计算) executeThisFunctionInAnyCase()将在任何情况下执行

到目前为止,有50多个答案,但没有人提到我在这种情况下通常会怎么做!(例如,一个由几个步骤组成的操作,但使用状态机或函数指针表将是多余的):

if ( !executeStepA() )
{
    // error handling for "A" failing
}
else if ( !executeStepB() )
{
    // error handling for "B" failing
}
else if ( !executeStepC() )
{
    // error handling for "C" failing
}
else
{
    // all steps succeeded!
}

executeThisFunctionInAnyCase();

优点:

最终不会有巨大的缩进水平 错误处理代码(可选)出现在失败函数调用之后的那几行中

缺点:

如果有一个步骤不是仅仅包含在一个函数调用中,会变得很糟糕吗 如果除了“按顺序执行步骤,如果一个失败就终止”之外,还需要任何流,那么就会变得很糟糕。

假设所需的代码是我目前看到的:

bool conditionA = executeStepA();
if (conditionA){
    bool conditionB = executeStepB();
    if (conditionB){
        bool conditionC = executeStepC();
        if (conditionC){
            ...
        }
    }
}    
executeThisFunctionInAnyCase();

我想说,正确的方法,因为它是最容易阅读和最容易维护的,应该有更少的缩进级别,这是(目前)这个问题的目的。

// Pre-declare the variables for the conditions
bool conditionA = false;
bool conditionB = false;
bool conditionC = false;

// Execute each step only if the pre-conditions are met
conditionA = executeStepA();
if (conditionA)
    conditionB = executeStepB();
if (conditionB)
    conditionC = executeStepC();
if (conditionC) {
    ...
}

// Unconditionally execute the 'cleanup' part.
executeThisFunctionInAnyCase();

这避免了对gotos、异常、dummy while循环或其他困难结构的任何需求,只需继续手头的简单工作。

Don't. Sometimes you need the complexity. The trick is how you do it. Having the "what you do when the condition exists" may take up some room, making the if statement tree appear larger than it really is. So instead of doing things if a condition is set, just set a variable to a specific value for that case( enumeration or number, like 10,014. After the if tree, then have a case statement, and for that specific value, do whatever you would have done in the if tree. It will lighten up the tree. if x1 if x2 if x3 Var1:=100016; endif endif end if case var=100016 do case 100016 things...

你可以把所有的if条件,按照你想要的格式放在它们自己的函数中,返回执行executeThisFunctionInAnyCase()函数。

从OP中的基本示例来看,条件测试和执行可以这样分离;

void InitialSteps()
{
  bool conditionA = executeStepA();
  if (!conditionA)
    return;
  bool conditionB = executeStepB();
  if (!conditionB)
    return;
  bool conditionC = executeStepC();
  if (!conditionC)
    return;
}

然后被这样称呼;

InitialSteps();
executeThisFunctionInAnyCase();

如果c++ 11 lambda是可用的(OP中没有c++ 11标记,但它们可能仍然是一个选项),那么我们可以放弃单独的函数,并将其包装为lambda。

// Capture by reference (variable access may be required)
auto initialSteps = [&]() {
  // any additional code
  bool conditionA = executeStepA();
  if (!conditionA)
    return;
  // any additional code
  bool conditionB = executeStepB();
  if (!conditionB)
    return;
  // any additional code
  bool conditionC = executeStepC();
  if (!conditionC)
    return;
};

initialSteps();
executeThisFunctionInAnyCase();