管理if语句

ant*_*009 10 c

gcc 4.4.3 c89

我有一些函数初始化一些硬件并返回true或false.如果为false,那么我必须以相反的顺序取消初始化.

但是,我的代码对所有if语句看起来都很不整洁.

例如,每个函数都可以返回true或false.这是一个样本.正如您所看到的,代码看起来非常不整洁.我只是在寻找有关如何清理它以使其更易于管理且可能更糟糕的任何建议?

非常感谢任何建议,

if(init_A() == TRUE) {
 if(init_B() == TRUE) {
  if(init_C() == TRUE) {
   if(init_D() == TRUE) {
    if(init_E() == TRUE) {
     /* ALL STARTED OK */    
    }
    else {
     uninit_A();
     uninit_B();
     uninit_C();   
     uninit_D();    
    }
   }
   else {
    uninit_A();
    uninit_B();
    uninit_C();   
   }
  }
  else {
   uninit_A();
   uninit_B();
  }
 }
 else {
  /* Failed to initialize B */
  uninit_B(); 
 }
}
else {
 /* Failed to start */
}
Run Code Online (Sandbox Code Playgroud)

ada*_*amk 24

if(init_A() != TRUE) {
    goto EndA;
}
if(init_B() != TRUE) {
    goto EndB;
}
if(init_C() != TRUE) {
    goto EndC;
} 
if(init_D() != TRUE) {
    goto EndD;
}
if(init_E() != TRUE) {
    goto EndE;
} 
...
return;
EndE: uninitD();
EndD: uninitC();
EndC: uninitB();
EndB: uninitA();
EndA: return;
Run Code Online (Sandbox Code Playgroud)

  • @robUK,@ Jacob - 我说,使用正确的工具完成任务,不带偏见. (4认同)
  • +1:保留逻辑,减少重复(非常通话),提高可读性,并有勇气在面对不可避免的goto警察时使用`goto`. (4认同)
  • "异常处理"是C中极少数地方之一,"goto"有时是允许的(当然,我认为). (3认同)

caf*_*caf 8

这是一个非常常见的问题,其中"init"步骤对应于malloc()或类似的东西lock(),而"uninit"步骤对应于free()和之类的东西unlock().当资源必须严格按照分配的相反顺序解除分配时,尤其是一个问题.

这是使用goto合理的一种情况:

int somefunc()
{
    int retval = ERROR;

    if (init_A() != TRUE)
        goto out_a;

    if (init_B() != TRUE)
        goto out_b;

    if (init_C() != TRUE)
        goto out_c;

    if (init_D() != TRUE)
        goto out_d;

    if (init_E() != TRUE)
        goto out_e;

    /* ALL STARTED OK */
    /* ... normal processing here ... */
    retval = OK;

    uninit_E();
  out_e:
    uninit_D();
  out_d:
    uninit_C();
  out_c:
    uninit_B();
  out_b:
    uninit_A();
  out_a:
    return retval;
}
Run Code Online (Sandbox Code Playgroud)


Jac*_*kin 7

我会遍历一个函数指针数组,在循环中调用函数,然后如果该函数返回false,则执行相应的uninit_*函数.

这是一个例子:

void (*inits[5]) (void);
void (*uninits[4]) (void);

int main(void) {
   inits[0] = init_A;
   inits[1] = init_B;
   inits[2] = init_C;
   inits[3] = init_D;
   inits[4] = init_E;

   uninits[0] = uninit_A;
   uninits[1] = uninit_B;
   uninits[2] = uninit_C;
   uninits[3] = uninit_D;

   for(int i = 0; i < 5; i++) {
      if((*inits[i])() != TRUE) {
         int j = (i < 4) ? i : 4; 
         while(j--) {
             (*uninits[j])();
         }
         break;
      }
   }
   return 1;
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*x F 6

BOOL a = FALSE, b = FALSE, c = FALSE, d = FALSE, e = FALSE;

if ( (a = init_A())  &&  (b = init_B())  &&  (c = init_C())  && (d = init_D())  && (e = init_E()) )
{
}
else
{
    if ( e ) uninit_E();
    if ( d ) uninit_D();
    if ( c ) uninit_C();
    if ( b ) uninit_B();
    if ( a ) uninit_A();
}

uninit函数按直接顺序调用,如代码中所示.如果需要反向顺序,只需更改它.

  • @crypto:逻辑AND(和逻辑OR)必须从左到右进行评估,因为它们具有短路行为:如果左侧完全确定最终结果,则必须完全跳过右侧. (2认同)