当代码流是这样的:

if(check())
{
  ...
  ...
  if(check())
  {
    ...
    ...
    if(check())
    {
      ...
      ...
    }
  }
}

我通常看到这种方法可以避免上述混乱的代码流:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(0);

有什么更好的方法可以避免这种工作/黑客,从而使其成为更高级别(行业级别)的代码?

任何跳出盒子的建议都是欢迎的!


当前回答

当然不是答案,而是一个答案(为了完整起见)

而不是:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(0);

你可以这样写:

switch (0) {
case 0:
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
}

这仍然是一个伪装的goto,但至少它不再是一个循环。这意味着你不需要非常仔细地检查是否有一些继续隐藏在块的某处。

构造也非常简单,您可以希望编译器会优化它。

正如@jamesdlin所建议的,你甚至可以把它隐藏在一个宏后面

#define BLOC switch(0) case 0:

然后像这样使用它

BLOC {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
}

这是可能的,因为C语言语法期望在开关之后有一个语句,而不是一个括号中的块,并且您可以在该语句之前放置一个case标签。到目前为止,我还没有看到允许这样做的意义,但在这种特殊情况下,将开关隐藏在一个漂亮的宏后面是很方便的。

其他回答

当然不是答案,而是一个答案(为了完整起见)

而不是:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(0);

你可以这样写:

switch (0) {
case 0:
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
}

这仍然是一个伪装的goto,但至少它不再是一个循环。这意味着你不需要非常仔细地检查是否有一些继续隐藏在块的某处。

构造也非常简单,您可以希望编译器会优化它。

正如@jamesdlin所建议的,你甚至可以把它隐藏在一个宏后面

#define BLOC switch(0) case 0:

然后像这样使用它

BLOC {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
}

这是可能的,因为C语言语法期望在开关之后有一个语句,而不是一个括号中的块,并且您可以在该语句之前放置一个case标签。到目前为止,我还没有看到允许这样做的意义,但在这种特殊情况下,将开关隐藏在一个漂亮的宏后面是很方便的。

如果你的代码有一个很长的If ..else If ..else语句块,你可以尝试在函子或函数指针的帮助下重写整个块。这可能并不总是正确的解决方案,但通常是正确的。

http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html

如果你不需要在执行过程中引入局部变量,那么你通常可以将其平化:

if (check()) {
  doStuff();
}  
if (stillOk()) {
  doMoreStuff();
}
if (amIStillReallyOk()) {
  doEvenMore();
}

// edit 
doThingsAtEndAndReportErrorStatus()

也许就像这样

#define EVER ;;

for(EVER)
{
    if(!check()) break;
}

或者使用异常

try
{
    for(;;)
        if(!check()) throw 1;
}
catch()
{
}

使用异常还可以传递数据。

如果对所有错误使用相同的错误处理程序,并且每一步返回一个bool值指示成功:

if(
    DoSomething() &&
    DoSomethingElse() &&
    DoAThirdThing() )
{
    // do good condition action
}
else
{
    // handle error
}

(类似于tyzoid的回答,但条件是动作,&&防止在第一次失败后发生额外的动作。)