Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C-do{..}while(0);是否可以从代码中删除,但不包括嵌套用法?_C++_C - Fatal编程技术网

C++ C-do{..}while(0);是否可以从代码中删除,但不包括嵌套用法?

C++ C-do{..}while(0);是否可以从代码中删除,但不包括嵌套用法?,c++,c,C++,C,do{…}while(0) do{}while(0)的用法是因为我不想使用长if else嵌套条件语句。我最终在失败时中断并退出循环,并保证我的函数至少会被遍历一次 现在,代码警告工具出现了问题,我在使用do{…}while(0)时收到了警告 nested if(){}else{}的使用可读性较差,复杂度较高。让代码有死代码 如果我排除嵌套if(){}else{}和do{}while(0),我们是否留下了一些其他方法使代码具有可读性和可理解的逻辑 if(status_of_funcA_ok !=

do{…}while(0)

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

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

nested 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);

您可以使用
goto
而不是
do{},同时(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++中,可以使用<代码>()/<代码>和<代码>尝试/捕获< /代码>:

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

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


最佳实践是用嵌套的if-else语句替换if-else条件,但我认为使用do{..}while(0);作为替代者,情况会更糟。这是非常非常规的,任何阅读它的人都不会真正将它与if-else语句联系起来

为了使嵌套的if-else语句更具可读性,您可以做一些事情。以下是一些建议:

  • 优化你的逻辑——有时候当你“重构”你的逻辑时,你可以去掉很多if子句,比如分组相同的项

  • use switch()-与if-else语句相比,switch通常更具可读性。您可以将一个枚举与每个案例关联,并可以进行切换

  • 用函数封装复杂的逻辑


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

  • 你不必担心它的美丽
  • 编译器也不必在{0}时抱怨
    do
  • 更重要的是,通过添加一点模块化,程序的可读性可能会提高一点

    在任何情况下,在执行此操作之前,最好检查编译器是否处于非常迂腐的模式,并且您可能希望将其关闭。这可能会使警告消失

    党卫军


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

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

    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个条件)
    • 条件很复杂,您使用/建立了重要状态,因此无法 将元素分离为函数
    • 您处于异常不友好的环境中,或者您的
      中断
      -ing代码路径为 事实上并非例外
    您可以对此做些什么:

    让警告静音。毕竟这只是一个警告;我看不出会被这个警告抓住的“典型错误”(比如键入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, ...);
      }
    }
    
    这可以说是可读性较差,更糟糕的是,您将序列分开,这可能会导致一个非常可疑的类(在该类中,成员可能仅按特定顺序调用)


    这可能允许将中断转换为早期回报,这是更可接受的:

    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()
    无法轻松地隔离到单个函数中时

    对这个问题解释得不多,现在已经接近了(你能举一个具体的例子说明你的plz代码的一部分吗?也许可以重写不同的代码。编译器可以警告他们喜欢的任何事情;在所有情况下避免所有警告是不切实际的。大多数警告都很重要,但如果你知道你在做什么(即,在这种情况下,你实际上比编译器更了解),你可以忽略它们。我举了一个例子!希望它能更容易理解。throw()和catch()应该只保留在特殊情况下(例外)。将它们用作流控制结构是不好的做法。谢谢你的回答。我认为goto/return是一个更好的选择,但是..愚蠢的讨厌的工具也将这些东西作为警告。由于多次中断,goto的使用。由于我使用的是C,throw和catch将不适用,我可以使用sub-helper函数指针,它将在一个循环中结束每个条件,我可以运行这些函数。但是对于或多或少4到5个条件检查的小函数,这种方法在嵌入式编程中可以接受吗?这是一个严重的疑问,因为我对这个行业非常陌生。@bancsy:原则上它们是流控制结构,如果不控制流,你还能用它们吗?它们应该用于转义没有意义继续的代码路径,是否会发生这种情况取决于您的情况。通常,您可以使用一个函数来检查导致错误的前提条件