C-do{.}while(0);可以从代码中删除,不包括嵌套的if-else用法

C - do{..} while(0); can be removed from code excluding usage nested if else?

本文关键字:删除 代码 不包括 嵌套 用法 if-else while C-do      更新时间:2023-10-16

do{…}while(0)

do{}while(0)的用法是因为,我不想使用长if-elses嵌套的条件语句。我最终在失败时中断并退出循环,并保证我的函数至少会被遍历一次。

现在,代码警告工具出现了问题,我在使用do时收到了警告{...}while(0)

嵌套if(){}else{}的用法可读性较差,非常复杂。并且让代码具有死代码。

如果我排除嵌套的if(){}else{}do{}while(0),我们是否用其他方法让代码可读并具有可理解的逻辑;

if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
do{
   if(status_of_funcA_ok != funcA())
   break;
   if (status_of_funcB_ok != funcB())
   break;
   if (status_of_funcC_ok != funcC())
   break;
  }while(0);

do while{0}循环的完整逻辑移动到一个函数,并用return替换break。并调用函数,而不是循环。

  1. 你不必担心美丽
  2. 编译器也不必抱怨do while{0}

更重要的是,通过添加一点模块化,程序可能会更可读。

无论如何,在执行此操作之前,最好检查您的编译器是否处于极其迂腐的模式,您可能需要关闭该模式。这可能会消除警告。

ss。

附言:你似乎不需要函数的返回值,但你可以用它来获得哪个函数成功的线索。

我也在使用这个模式,对于那些想知道的人来说,这里有一个抽象的例子:

do   // while(0) for break
{ 
  state1 = 0;
  if (cond1())
  {
    if (cond2())
      break;
    state1 = opA();
  }
  if (cond3() || state1 && state1->cond4())
    break;
  ... 
  Triumph(state1, ...);
  // often here: return
}
Failure(state1, ...);

我认为这在以下情况下是有效的:

  • 你有一个很长的序列(比如说,>~6个条件)
  • 条件很复杂,并且你使用/建立了重要的状态,所以你不能将元素隔离为函数
  • 您所处的环境对异常不友好,或者您的break代码路径为实际上不是例外

你能做些什么:

使警告静音毕竟这只是一个警告,我看不出会被这个警告抓住的"典型错误"(比如键入0而不是您的条件)

现在,这太傻了。警告的典型错误是例如while (a1!=a1)而不是while (a1!=a2)。[/edit]

分解函数,将状态移动到类
这将把上面的代码转换为:

struct Garbler
{
  State1 state1;
  bool Step1()
  {
     state1 = 0;
     if (cond1())
     {
        if (cond2())
          return false;
        state1 = opA();
     }
     return true;
  }
  bool Step2()
  {
     return cond3() || state1 && state1->cond4();
  }
  .. 
  void Run()
  {
    if (Step1() && Step2() && ... && Step23())
      Triumph(state1, ...);
    else
      Failure(state1, ...);
  }
}

这可以说是可读性较差的,更糟糕的是,您将序列拆开,这可能会导致一个非常可疑的类(其中成员只能按特定顺序调用)。

Scopeguards
这可能允许将破发转换为更可接受的早期回报:

state1 = 0;
ScopeGuard gFailure = MakeGuard(&Failure, ByRef(state1), ...);
if (cond1())
{
   if (cond2())
     return;
   state1 = opA();
}
if (cond3() || state1 && state1->cond4())
  return;
// everything went ok, we can dismiss the scopeguard
gFailure.Dismiss();
Triumph(state1, ...);

它们可以用C++0x更优雅地编写,保留流,但解决方案也不那么灵活,例如,当Failure()无法轻松隔离为单个函数时。

嵌套的if-else语句可能会变得非常不可读,但我认为使用do{..}while(0);作为替代品会更糟糕。这是非常非传统的,任何其他阅读它的人都不会真正将其与if-else语句联系起来。

您可以做一些事情来提高嵌套if-else语句的可读性。一些建议是:

  1. 优化你的逻辑-当你"重构"你的逻辑时,有时你可以去掉很多if子句,比如对相同的项进行分组。

  2. use switch()-与if-else语句相比,switch通常更可读。您可以将枚举与每个案例相关联,并且可以切换此项。

  3. 用函数封装复杂逻辑

您可以使用goto而不是do {} while(0)break。这是不可读的,也不是好的做法。我认为,对于每一种特定的情况,都有一种更好的方法来避免深层的if/else结构。例如,有时使用函数调用会有所帮助:

例如,而不是:

if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}

你可以写:

if (check_funcs() == 0) {
   great();
}
int check_funcs() {
   if (status_of_funcA_ok != funcA())
     return -1;
   if (if(status_of_funcB_ok != funcB())) 
     return -2;
   if (if(status_of_funcC_ok != funcC())) 
     return -3;
   return 0; /* great */
}

有时,您可以使用exit()

此外,在c++中,您可以使用throw()try/catch:

try {
   /* */
  throw (this error);
   /* */
  throw (that error);
} catch (this error) {
} catch (that error) {
}

如果有更多条件需要检查,请避免使用if{} else{},

最佳做法是用switch case 替换if-else条件