2012-02-09 152 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; 
}