28

次のループで、期待される数字の代わりに文字をcin入力すると、無限ループに入ります。なぜこれが起こるのか誰か説明してもらえますか?

を使用するcin場合、入力が数値でない場合、これを検出して上記の問題を回避する方法はありますか?

unsigned long ul_x1, ul_x2;

while (1)
{
  cin >> ul_x1 >> ul_x2;
  cout << "ux_x1 is " << ul_x1 << endl << "ul_x2 is " << ul_x2 << endl;
}
4

4 に答える 4

36

無限ループは常に発生しますが、本当に知りたいのは、無限ループがフリーランする原因となる各ループ反復で cin が入力を求め続けない理由です。

その理由は、説明した状況では cin が失敗し、それらの変数への入力をこれ以上読み取らないためです。cin に不正な入力を与えると、cin は失敗状態になり、コマンド ラインに入力を求めるプロンプトを表示しなくなり、ループがフリーランします。

簡単な検証のために、cin が失敗状態にあるかどうかを確認することにより、cin を使用して入力を検証することができます。失敗が発生すると、失敗状態をクリアし、ストリームに不良な入力を強制的に破棄させます。これにより、cin が通常の操作に戻るため、さらに入力を求めることができます。

  if (cin.fail())
  {
     cout << "ERROR -- You did not enter an integer";

     // get rid of failure state
     cin.clear(); 

     // From Eric's answer (thanks Eric)
     // discard 'bad' character(s) 
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  }

より高度な検証を行うには、最初に文字列を読み取り、その文字列に対してより洗練されたチェックを行って、期待したものと一致することを確認します。

于 2011-05-03T02:48:59.820 に答える
11

注意

次の解決策に注意してください。あなたのケースのエラーをクリアすることはまだ完了していません。それでも無限ループが発生します。

if (cin.fail())
{
     cout << "Please enter an integer";
     cin.clear();
}

完全なソリューション

その理由は、ストリームの失敗状態をクリアし、未処理の文字を破棄する必要があるためです。そうしないと、まだ悪い文字が残っており、無限ループが発生します。これを達成するには、単に std::cin.ignore() を実行できます。例えば、

if (cin.fail())
{
         cout << "Please enter an integer";
         // clear error state
         cin.clear();
         // discard 'bad' character(s)
         cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

別の解決策

getlineと を使用しstringstreamて達成することもできます。以下に簡単な例を示します。

   string input;
   while (1)
   {
      getline(cin, input);
      stringstream(input) >> x;
      cout << x << endl;
   }
于 2011-05-03T03:02:35.240 に答える
2

おそらく、その理由は、

  1. cin はストリーミング関数です。数字の代わりに非数字が入力された場合、それは無視されます。また、再入力を求められます。
  2. 数値入力を行った場合でも、無限ループにいるため、さらに入力を求めるプロンプトが表示されます。

この問題は次のように解決できます。 1. 文字列入力を受け取る関数を作成します。2. 変換後、数値として返します。変換には strtod() を使用します。

お役に立てれば :)

于 2011-05-03T03:08:46.670 に答える