2017-12-04 1 views
0

私は彼のC++割り当ての1つで友人を手伝っていましたが、次のコードスニペットがMSVCで例外をスローすることがわかりましたが、G ++でコンパイルするときには全く同じコードがうまくいきます。例外は、getValue()というこの関数が何も返さなかったために返されました。コンパイラをG ++からMSVCに切り替えるときに、このswitch文が何も返さないのはなぜですか?

string getValue(int value) { 

    ostringstream convert; 

    string rtnValue; 

    switch (value) { 
    case 11: 
    { 
     rtnValue = "J"; 
     break; 
    } 
    case 12: 
    { 
     rtnValue = "Q"; 
     break; 
    } 
    case 13: 
    { 
     rtnValue = "K"; 
     break; 
    } 
    case 14: 
    { 
     rtnValue = "A"; 
     break; 
    } 
    default: 
    { 
     // 
     // if the value is a a number, we assume it is 2..10 
     // 
     convert << value;   // use a stream to convert the number 
     rtnValue = convert.str(); // into a string 
     if (value < 2 || value > 10) 
     { 
      rtnValue = "ERROR" + rtnValue + "ERROR"; 
     } 
    } 
    return rtnValue; 
    } 
} 

このプログラムは、整数を文字列に変換します。 11〜14の数値については、switch文を使用します(これは最適な実装ではありませんが、導入クラスです)。

これは、最後に別のreturn文を追加することで簡単に解決できることがわかりました。

string getValue(int value) { 

    ostringstream convert; 

    string rtnValue; 

    switch (value) { 
     case 11: 
     { 
      rtnValue = "J"; 
      break; 
     } 
     case 12: 
     { 
      rtnValue = "Q"; 
      break; 
     } 
     case 13: 
     { 
      rtnValue = "K"; 
      break; 
     } 
     case 14: 
     { 
      rtnValue = "A"; 
      break; 
     } 
     default: 
     { 
      // 
      // if the value is a a number, we assume it is 2..10 
      // 
      convert << value;   // use a stream to convert the number 
      rtnValue = convert.str(); // into a string 
      if (value < 2 || value > 10) 
      { 
       rtnValue = "ERROR" + rtnValue + "ERROR"; 
      } 
     } 
     return rtnValue; 
    } 
    return rtnValue; 
} 

これでMSVC用に修正されました(また、チェックした場合はG ++と仮定しています)。

この修正はなぜ機能しましたか? MSVCとG ++はswitch文に関して括弧を異なる方法で扱いますか?

答えて

3

最初の例では、return rtnValueは間違った場所にあり、既定のケースに当たったときのみ動作します。

2番目の例では、正しい場所にreturn rtnValueを追加しています(もう1つは安全に削除できます)。

MSVCではなくGCCで動作する理由については、戻り値が正しい場所にない場合、有効ではないC++(すべてのパスに戻り値があるわけではない)なので、 C++コンパイラでのコンパイルエラー。

実際には中カッコ{}が使用されているという問題があり、あなたの友人はデフォルトケースの閉じ括弧が実際にswitch文を閉じたと思っていましたが、そうではありません。

また、ケースステートメントのいずれかに中カッコを入れる必要はありません。中括弧はこのようにしてスコープ(特定のケースの一時変数など)を導入することができますが、あなたの例では混乱の原因になります。

0

戻り値

は、最初のサンプルであなたのreturn文はswitchブロックの実行は、他のすべてのケースでbreak文で終わるだけ以来default場合に適用されます。

デフォルト以外では、関数の戻り値は初期化されていません。 MSVCはデバッグ中に警告します(詳細についてはhttps://docs.microsoft.com/en-us/visualstudio/debugger/how-to-use-native-run-time-checksを参照してください)。しかし、GCCはデバッグしません。この問題はコンパイル時に検出される可能性がありますが、それに依存することはできません。

return 2番目のサンプルに追加された文が正しい。余分になる元のものを取り除くことができます。

サスペンダー

switchブロック内のかっこは不要であり、ここでは混乱を導入することを注意してください。単一のcaseで使用するためだけにローカル変数を作成した場合にのみ便利です。とにかく、中かっこはswitchブロックの中かっこよりもインデントしなければなりません。この部分

} 
return rtnValue; 
} 

は、誤ったインデントをはっきりと示しています。 2番目の例で使用されているインデントは、この問題の良い解決策の1つです。

0

これはあなたのreturn文が間違っているブロック、すなわち、switchブロック内にある問題

default: 
{ 

    convert << value;   // use a stream to convert the number 
    rtnValue = convert.str(); // into a string 
    if (value < 2 || value > 10) 
    { 
     rtnValue = "ERROR" + rtnValue + "ERROR"; 
    } 
} 
return rtnValue; 
} 

です。

何が起こるかは、ケースが満たされたときに、switchが壊れてしまったためです(これは現在、switch文の外にあるためです)。

これを修正するには、return文を関数の最後のswitch文の外に移動する必要があります。

この修正は、お客様が提供した2番目のコードに相当します。

でも、2番目のコードでも、returnステートメントを削除してください。

関連する問題