web-dev-qa-db-ja.com

数値が予想されるときに文字列を入力するときのcinによる無限ループ

次のループでは、予想される数値の代わりに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;
}
22
chanwcom

常に無限ループが発生しますが、本当に知りたいのは、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');

  }

より高度な検証を行うには、最初に文字列を読み込み、文字列に対してより高度なチェックを行って、期待どおりであることを確認することをお勧めします。

31
Doug T.

注意

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

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');
}

別の解決策

getlinestringstreamを使用して達成することもできます。これが簡単な例です。

   string input;
   while (1)
   {
      getline(cin, input);
      stringstream(input) >> x;
      cout << x << endl;
   }
9
Eric Z

おそらく、それは、

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

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

お役に立てれば :)

2
itsols

別の選択肢は 演算子! 、これはメンバー関数と同等です fail()

//from Doug's answer
if ( !cin )
{
   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');
}
0
Hani Shams