C ++の無限ループ[複製]
-
06-07-2019 - |
質問
この質問にはすでに回答があります:
私は、C ++を学習し、小さなプログラムを書いています。以下はそのようなプログラムの1つです。
// This program is intended to take any integer and convert to the
// corresponding signed char.
#include <iostream>
int main()
{
signed char sch = 0;
int n = 0;
while(true){
std::cin >> n;
sch = n;
std::cout << n << " --> " << sch << std::endl;
}
}
このプログラムを実行し、入力を適度に小さい絶対値に保つと、期待どおりに動作します。しかし、10000000000などのより大きな入力を入力すると、プログラムは同じ出力を繰り返し吐き出します。入力のいくつかの組み合わせにより、不安定な動作が発生します。例:
#: ./int2ch
10
10 -->
10000000000
10 -->
10 -->
10 -->
10 -->
プログラムは&quot; 10-&gt;を吐き出します。 &quot;殺されるまで。 (この特定の入力シーケンスでは、プログラムの出力の速度が不規則に変化します。)また、大きな値の出力は、以前の正当な入力と現在の不正な入力の値によって決定されることに気付きました。
何が起こっているのですか? (プログラムの修正は気にしません。それは簡単です。理解したいです。)
解決
基本的に、 cin
ストリームは失敗状態であるため、読み込もうとするとすぐに戻ります。次のように例を書き換えます:
#include <iostream>
int main()
{
signed char sch = 0;
int n = 0;
while(std::cin >> n){
sch = n;
std::cout << n << " --> " << sch << std::endl;
}
}
cin&gt;&gt; n
は、 cin
への参照を返します。これは、「善」をテストできます。条件付きで。基本的に&quot; while(std :: cin&gt;&gt; n)
&quot; &quot;標準入力から正常に読み取ることができますが、次のことを行います&quot;
編集:最後に入力された適切な値を繰り返し出力する理由は、それがnで正常に読み取られた最後の値であり、失敗した読み取りがnの値を変更しないためです
編集:コメントに記載されているように、エラー状態をクリアし、おそらく次のような動作をやり直すことができます。
#include <iostream>
#include <climits>
int main() {
signed char sch = 0;
int n = 0;
while(true) {
if(std::cin >> n) {
sch = n;
std::cout << n << " --> " << sch << std::endl;
} else {
std::cin.clear(); // clear error state
std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
}
}
}
他のヒント
はい、エヴァン・テランはすでにほとんどのものを指摘しました。追加したいことの1つは(まだコメントをコメントできないためです)、istream :: ignoreへの呼び出しの前にistream :: clearへの呼び出しを配置する必要があるということです。理由は、ストリームがまだ失敗状態にある場合、istream :: ignoreは同様に何もしないことです。
32ビットマシンを使用している場合、10000000000は大きすぎてintで表現できません。また、intをcharに変換すると、コンパイラーに応じて0..255または-128..127のみが得られます。
ここでの1つの問題は、 char
のサイズが1バイトであるため、-127から128の間の数値しか保持できないことです。一方、 int
、通常は4バイトで、より大きな値をとることができます。 2番目の問題は、 int
に対しても大きすぎる値を入力していることです。