2012-02-09 61 views
0

我所有的功能是这样的:C:返回错误的代码风格?

short Function() 
{ 
    short ret = 0; 

    ret = FunctionA(); 
    if(ret != 0) return ret; 

    ret = FunctionB(); 
    if(ret != 0) return ret; 

    ret = FunctionC(); 
    if(ret != 0) return ret; 

    return 0; 
} 

有没有写这个一个更好的办法吗?无需重复

if(ret != 0) return ret; 

所有的时间?

回答

7

如果使用短路||像其他答案建议是不是一种选择,你可以定义一个宏:

#define TRY(var, x) if ((var = (x))) return var 

然后在你的代码:

short Function() 
{ 
    short ret; 

    TRY(ret, FunctionA()); 
    TRY(ret, FunctionB()); 
    TRY(ret, FunctionC()); 

    return 0; 
} 

注意:你决定使用宏时应该非常小心,但在这种情况下,我认为它可以可以是一个干净的方式来解决问题。但是,必须提到的是,这些陈述隐含了这样一个事实,即函数可以在每一个函数中尽早返回。如果您打开资源句柄(文件描述符,指向malloc ed数据的指针,...),它们将会泄漏。你和每个使用代码的人都应该意识到这一点,并为比这更复杂的情况使用适当的错误处理和清理例程。

+1

非常酷的使用宏,从来不知道你可以在宏中使用if语句。 – Annabelle 2012-02-09 20:11:15

+1

'do {ret =(x);如果(ret!= 0)返回ret; } while(0)'是一个更好的选择! – Marlon 2012-02-09 20:11:31

+2

然后把它交给n00b进行维护:( – KevinDTimm 2012-02-09 20:11:49

5
short Function() 
{ 
    short ret = 0; 

    if(
     (ret = FunctionA()) != 0 || 
     (ret = FunctionB()) != 0 || 
     (ret = FunctionC()) != 0 
    ) 
    { 
     return ret; 
    } 

    return 0; 
} 
+2

+1我为这一个投票 - 在宏中隐藏return语句和变量名(另一个答案)是我不想处理的代码。 – justin 2012-02-09 20:13:43

+0

@Justin:嗯,如果它在代码库中的使用正确和一致,它可以非常干净和方便,恕我直言。这不像在头脑中保持这一点(使用该宏来传播子功能中的错误)是非常苛刻的。 – 2012-02-09 20:21:11

+0

@MrLister:是的,对不起 - 已删除! – 2012-02-09 20:32:36

0

这应该是等价的,如果我没有弄错

short Function() 
{ 
    short ret = FunctionA(); 
    if(ret == 0) 
    { 
     ret = FunctionB(); 
     if(ret == 0) 
     { 
      ret = FunctionC(); 
     } 

    } 
    return ret; 
} 
0

你可以写:

short ret; 
if (ret = FunctionA()) return ret; 
if (ret = FunctionB()) return ret; 
if (ret = FunctionC()) return ret; 

你可能惊讶几个同事那样的,但!

一种替代,使用短路,由@启发添的帖子:

short ret; 
return (ret = FunctionA()) || (ret = FunctionB()) || (ret = FunctionC()) ? ret : 0; 

在C++中,你可以说:

if (short ret = FunctionA()) return ret; 
+1

返回||运算符将不起作用,因为它返回1或0,而不是ret。你可以写'return(ret = FunctionA())|| (ret = FunctionB())|| (ret = FunctionC())? ret:0;'虽然。 – 2012-02-09 20:22:44

+0

@MrLister:的确,谢谢。不过,我想强调,在任何情况下你都会返回'ret'。 – 2012-02-09 20:32:15

+0

好的,这可能是正确的做法。它确实看起来有点傻,不好意思... – 2012-02-09 20:37:13

1

有很多方法来重写,但我可以”不要想起比你更直接和更容易的事情。
下面是另一个变体,特别是旨在最大限度地减少if ... return陈述的数量。

int i; 
for (i = 0; i<3; +i) { 
    switch (i) { 
     case 0: ret = FunctionA(); break; 
     case 1: ret = FunctionB(); break; 
     case 2: ret = FunctionC(); break; 
    } 
    if (ret != 0) return ret; 
} 
return 0; 
+4

为什么有人会这样做? – Marlon 2012-02-09 20:22:45

+0

嗯,首先,这可以让你做一些优化,因为你可以在找到正确答案之前计算循环运行多少次。假设FunctionB比FunctionA更经常是正确的,那么你可以先将FunctionB放入。除此之外,好吧,这只是原始问题的另一个变种。 – 2012-02-09 20:30:51

0
short Function() { 

    short temp; 

    return (temp = FunctionA()) ? temp : (temp = FunctionB()) ? temp : FunctionC(); 

} 
2

我走另一条路,并显示你我是如何在实际中的程序做到这一点我写:

short Function() { 
    short ret = 0; 

    ret = FunctionA(); 
    if(ret != 0) { 
     SomeUsefulMessageOrAssertionHere(); 
     return ret; 
    } 
    ... 

它实际上减少上游错误处理代码,因为好书面诊断最好在现场处理。当然,它不会改变发生错误时必须采取的行动。

0

我一直很喜欢函数指针,我自己。

int main() 
{ 
    typedef ret-type (*Fptr)(... args-types ...); 

    const int N_FUNC = 3; 
    Fptr functions[] = { FunctionA, FunctionB, FunctionC }; 

    short ret = 0; 
    for(int i=0; ! ret && i < N_FUNCS; i++) 
     ret = functions[i]; 

    return ret; 
}