2017-12-03 10 views
2

私はいくつかの初期化を行い、それぞれがエラーコードを返す他の関数を呼び出します。この私の会社で最初に検出されたエラーの後にエラーコードを返します

int error_code = FirstFunction(); 
if (error_code != 0) { 
    return error_code; 
} 
error_code = SecondFunction(); 
if (error_code != 0) { 
    return error_code; 
} 
// etc... 

しかし、だけでなく、これはかなり面倒を見ない、それはまた、複数のreturn文を持ち、コンプライアンス上の理由:私はこのような最初に検出されたエラーの後に、この関数から戻ることができるようにしたいです許可されていません。

returnステートメントは1つだけですが、最初のエラーコードの後でも停止するように、これを並べ替える方法はありますか?

int error_code = FirstFunction(); 
if (error_code == 0) { 
    error_code = SecondFunction(); 
    if (error_code == 0) { 
     error_code = ThirdFunction(); 
     // etc... 
    } 
} 
return error_code; 

しかし、これはかなり速い不合理得ることができます:私は考えることができる唯一の方法は、if文を入れ子になったんです。これを行う別の方法がありますか?

EDIT:私のプログラムでは、0の戻りコードが成功(OK)とゼロ以外の手段失敗/エラー(OK、NOT)を意味

+0

だから、それが '1'の時にあなたは戻ってくるだろう? – coderredoc

+0

0以外のものはエラーなし、0以外のエラーはエラー –

+0

「error_code」のタイプを投稿します。 – chux

答えて

4

OKは成功の戻り値は、これらの機能のためには何でもあります)

error_code = FirstFunction(); 
if (error_code == 0) { 
    error_code = SecondFunction(); 
} 
if (error_code == 0) { 
    error_code = ThirdFunction(); 
} 
// etc... 
return error_code; 
1
if((error_code = FirstFunction()) || (error_code = SecondFunction()) || ...){ 
    return error_code ; 
} 

return error_code; //denoting no error. 

これがゼロ以外を返すのみ最初の関数を返します。考え方は、ifステートメントの場合、nonzeroを返す最初の関数は評価全体を短絡し、error_codeを返した関数からerror_codeを返します。また別のものは、代入文の値が割り当てられた値です。そういうわけで、これが機能します。まあ、例えば使用されるものがあるかどう-他

if(error_code = FirstFunction()) {} 
else if(error_code = SecondFunction()) {} 
... 

return error_code; 
+0

これは近いと私は比較のエラーコードをキャプチャする方法が好きですが、Benoitの答えは私が探していたものに少し近いです。 –

+1

注: 'else'は必要ありません。 – chux

+0

@chux:最後のものを意味しますか?以前私は 'FirstFunction'を2回呼び出すというタイプミスがありました。あなたはそれを意味しましたか? – coderredoc

0

もっと簡単な方法は、連続するだろうLinuxカーネルに:

int somefunc(whatever) 
{ 
    if (do_something()) { 
     ret = -EINVAL; 
     goto err; 
    } 
    if (do_something_else()) { 
     ret = -EPERM; 
     goto err; 
    } 
    /* ... */ 
    ret = 0; 
err: 
    some_mandatory_cleanup(); 
    return ret; 
} 

しかし、私はそれもあまり受けたことになるだろうと思います。 (あなたが叫ぶ前に、その全体のポイントは最終的に強制的なクリーンアップです。常に実行されるように調整されますが、それでもそれを外します)

本当に、私はあなたの最初のスニペット問題はあなたのガイドラインにあります。 return error_code;を1か所に書き込んでも、変数に保存されているエラーコードが常に正しいこと、または関数が必要となる可能性があるすべてのクリーンアップを完了することを保証するだけでは不十分です。

+0

ガイドラインを変更したいのと同じくらい、私たちの顧客からの全体的なプロジェクト要件の一部であり、手に負えません。 –

+0

そして、私はgotoを使ってみると私を撃つでしょう:D –

0

これらの関数はすべて同じ型のパラメータを持ち、同じ戻り値の型を持つ場合は、それらを関数配列に入れて反復することができます(メモリを割り当てます) 。エラーが見つかると、ループから抜けて戻ります。

int (*function_array[max_array])(); 
/*Fill the array with the functions you need*/ 

for(i=0;i<max_array;i++){ 
    if((error_code=function_array[i]())!=OK){ 
     break; 
    } 
} 

return error_code; 

次のコードは、同様に仕事をし、自分のコードを遵守しなければならない、あなたは巣にすべての関数呼び出しを持っていない

+0

私はOPに引数は言及されていませんが、このアプローチは、関数ポインタの配列を使って、同じ引数を使用するすべての関数に頼ります。 umberとタイプ。 – alk

+0

私はそれについて考えなかったのは本当です。たぶんそれはパラメータの別の配列で解決できるかもしれません。しかし、現時点では価値がないかもしれません。 – Nevado

1

リーンとクリーン(like this oneが、嫌わgotoのを避ける):

int foo(void) 
{ 
    int error_code; 

    do { 
    if (0 != (error_code = FirstFunction())) 
    { 
     break; 
    } 

    if (0 != (error_code = SecondFunction())) 
    { 
     break; 
    } 

    ... 

    } while (0); 

    return error_code; 
} 
012ルールを書きます

これは、より一般的なパターンに従います。0はOKですが、それ以外はすべてありません。必要に応じて)


を調整してあなたも、マクロを使用して、これを難読化することができます:ここで

#define RUN_AND_BREAK_ON_ERROR(rc, f, ...) \ 
    if (0 != (rc = f(__VA_ARGS__))) \ 
    { \ 
    break; \ 
    } 

int foo(void) 
{ 
    int error_code; 

    do { 
    RUN_AND_BREAK_ON_ERROR(error_code, FirstFunction, <args go here>); 
    RUN_AND_BREAK_ON_ERROR(error_code, SecondFunction, <args go here>); 
    ... 

    } while (0); 

    return error_code; 
} 
+0

@AnttiHaapala:なぜですか?どうしてこんなに頻繁に起こるのですか?:} – alk

+0

おそらく1,3,7-トリメチルキサンチン欠乏症候群です;)あまりにも多くのVisual Basic –

2

は失敗した機能に応じて、異なるエラーコードを返すことができる別の赤身の方法です:

int func(void) 
{ 
    int code; 
    int error_code = (code = FirstFunction()) ? code : 
        (code = SecondFunction()) ? code : 
        (code = ThirdFunction()) ? code : 0; 

    /* ... */ 

    return error_code; 
} 
関連する問題