2017-12-10 41 views
2

私は自分のコードで複数のbreakおよびgotoステートメントを取り除こうとしています。 ルールは、おしっこがサンプルコード MISRA C 2012ルール15.4繰り返しステートメントを終了するためにbreakまたはgotoステートメントを複数使用しないでください。

任意の繰り返し文で

を複数のブレークまたはgoto文を使用しないでくださいとおり:私はあれば、ネストされたステートメントで試してみましたが、終了するソリューションではありません

for(int32_t i = 0; i < 10; i++) { 
    if (i == number1) {     
     return_val = 2*number1 + number2; 
     break; 
    } 

    number1 += (5 * number2 + 2*number3); 

    if (i == number2) { 
     return_val = number1 + (3 * number3); 
     break;     
    } 

    number1 += 2 * number3; 

    if (i == number3) { 
     return_val = number1 + (2 * number2); 
    } 
} 

ループ。

また、breakの代わりに、goto文がある場合は修正プログラムがあります。後藤と

サンプルコード:

for(int32_t i = 0; i < 10; i++) { 
    if (i == number1) {     
     return_val = 2*number1 + number2; 
     goto LABE1; 
    } 

    number1 += (5 * number2 + 2*number3); 

    if (i == number2) { 
     return_val = number1 + (3 * number3); 
     goto LABE2;     
    } 

    number1 += 2 * number3; 

    if (i == number3) { 
     return_val = number1 + (2 * number2); 
    } 
} 
+1

厳密にMISRA(推奨事項)を守らなければ、自分自身に好意を持ち、** IGNORE ** 15.4と15.5を無視してください。私はこれらの2つのルールに従うと、決してより良いコードを見たことはありません。それはすべてを冗長にするだけです。あなたはブール値のフラグ(そして 'else if'のカスケード)を使って"修正 "することができます –

+0

@adrianoこれでどのようにループを終了できますか? – Amardeep

+0

変数 'i'を終了値' 10'に設定すると、ループを終了できます。これはフラグとしても使わなければならないので、 'number1 + =(5 * ...)'は実行されません。コードがループの終わりに達すると、終了条件が満たされたことがわかります。 - 'i = 10;を使うこともできます。 MISRAによって 'continue'が許可されていればDunnoになります。 – harper

答えて

3

Iは15.4と15.5は、2つの非常に論争のMISRAの提案だと思います。それらは必須ではありませんが、あなたの組織が承認している場合は、「不満」(tnx Andrew)として分類することをお勧めします。私の意見では、これらのルールに従うことで、コードをより冗長にし、読みにくくし、エラーを起こしやすくします。

私が言ったように、私の意見ですが、ステップバイステップのアプローチを試してみましょう。私は適切な名前を使用していませんが、ドメインから適切な名前を選ぶ必要があります。

旗とあなたは、単純な_Boolフラグを使用することができ、単一のbreak

を保ちます。あなたがstdbool.hを含むと仮定すると:

bool flag = false; 

for(int32_t i = 0; i < 10; i++) { 
    if (i == number1) {     
     return_val = 2*number1 + number2; 
     flag = true; 
    } else { 
     number1 += (5 * number2 + 2*number3); 

     if (i == number2) { 
      return_val = number1 + (3 * number3); 
      flag = true; 
     } else { 
      number1 += 2 * number3; 

      if (i == number3) { 
       return_val = number1 + (2 * number2); 
      } 
     } 
    } 

    if (flag) 
     break; 
} 

理想的にあなたが条件を記述する必要があり、flagのためのより良い名前を選択してください。ご覧のとおり、breakが1つありますが、わかりやすい価格で支払いました。

旗、私たちは何ができるのcontinue

breakを置き換えますか? continuebreakを交換し、ループ状態にフラグを使用します。

bool flag = true; 

for(int32_t i = 0; flag && i < 10; i++) { 
    if (i == number1) {     
     return_val = 2*number1 + number2; 
     flag = false; 
     continue; 
    } 

    number1 += (5 * number2 + 2*number3); 

    if (i == number2) { 
     return_val = number1 + (3 * number3); 
     flag = false; 
     continue; 
    } 

    number1 += 2 * number3; 

    if (i == number3) { 
     return_val = number1 + (2 * number2); 
    } 
} 

わずかに良いが、真実は、我々は、このコードの主な問題に対処していないということです。

このコードスニペットは、大きな機能の一部であるならば、真実は、我々は間違った問題に対処しているということである別の関数

に移動

。問題を引き起こす可能性がありますが、より大きな文脈でその使用をもたらすことができるのはbreakです。ではありません。 flagと私たちの最初の実装に似た別の関数で

for(int32_t i = 0; < 10; i++) { 
    if (foo(i, &number1, number2, number3, &return_value)) { 
     break; 
    } 
} 

:Cで我々は、我々はアウトパラメータを(それがこの結果を達成するための唯一の技術ではありません)を使用することができstd::optional<T>を持っていません。

if (i == *number1) {     
    *return_val = 2 * *number1 + number2; 
    return true; 
} 

// ... 

が適切な場合にconstを追加することを忘れないでください:あなたは無視することができるかどう

bool foo(int32_t i, int32_t* number1, int32_t* return_val) { 
    bool has_result = false; 

    if (i == *number1) {     
     *return_val = 2 * *number1 + number2; 
     has_result = true; 
    } else { 
     // ... 
    } 

    return has_result; 
} 

はさらに良いことに、15.5この関数は書くことと読むことを非常に簡単になります。私はこれがリファクタリングされることができます(多すぎる関数の引数、混合値&ポインタ、これらの2つの関数の間の結合が大きすぎます)が、ダミーの名前と周囲のコードの欠如により、私が強調したいのは、コードを別の機能に移すことです。

分岐内のコードが十分複雑な場合は、3つの別々の機能を導入することでさらにメリットが得られます。何が2 * *number1 + number2ですか?それは何を計算していますか?

コードレビュー(周囲のコードと実際の名前を含み、その目的を説明しています)に完全なコードを投稿してください。

+0

あなたは「自由に無視する」ことはできませんが、あなたの組織が承認している場合は、それらを「不満」に再分類することができます。 – Andrew

+0

@Andrewの説明に感謝します! –

0

これはかなりあいまいなアルゴリズムです。実際には、それは通常、多くのMISRAルールが沸き起こるものです。奇妙なコードを書くことを妨げます。私は確かに分かりませんが、このコードはさまざまなグローバル変数に依存しており、それを書く良い方法があるかもしれません。

しかし、もしアルゴリズムがあなたが書いたのとまったく同じで、そのまわりに道がないなら、それはそれです。その場合、別の(勧告的な)MISRAルールに違反する複数のreturn文でコードを書き直します。しかし、複数のブレーク/ゴートに反対するやや健全なルールよりも、そのルールから逸脱する方が良いです。

for(int32_t i = 0; i < 10; i++) { 
    if (i == number1) {     
     return 2*number1 + number2; 
    } 

    number1 += (5 * number2 + 2*number3); 

    if (i == number2) { 
     return number1 + (3 * number3); 
    } 

    number1 += 2 * number3; 

    if (i == number3) { 
     return number1 + (2 * number2); 
    } 

これは、質問のいずれかの選択肢よりも読みやすいです。

(あなたがuサフィックスもしなければならないことをMISRAに準拠するため、すべての整数定数を注意してください)

関連する問題