次のループでは、予想される数値の代わりに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;
}
常に無限ループが発生しますが、本当に知りたいのは、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');
}
より高度な検証を行うには、最初に文字列を読み込み、文字列に対してより高度なチェックを行って、期待どおりであることを確認することをお勧めします。
注意
次の解決策に注意してください。あなたのケースのエラーをクリアすることはまだ完了していません。 まだ無限ループになります!
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;
}
おそらく、それは、
この問題は次のように解決できます。1。文字列入力を受け取る関数を作成します。 2.変換後に数値として返します。変換にはstrtod()を使用します。
お役に立てれば :)