cin を呼び出したときに入力ストリームが空でない場合、cin はユーザーからの追加を待つ代わりに、既にバッファーにあるデータを使用します。抽出演算子を使用しているため、cin が変数に値を送信するときに、バッファ内の先頭の空白をスキップし、次の空白で停止します。
この行にブレークポイントを置きます。
cout << "\n What is your current salary? \t";
プログラムを実行し、Bob Smith と入力します。ブレークポイントに到達したら、文字列のフルネームの上にカーソルを置きます。「Bob Smith」ではなく「Bob」のみが格納されていることがわかります。「Bob Smith」はバッファーに入れられましたが、抽出演算子で cin を使用すると、先頭の空白をスキップし、次の値を変数に入れ、次の空白で停止します。これを実証するために、これを実行してみてください:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2;
cin >> str1;
cin >> str2;
cout << str1 << " " << str2 << "\n\n";
return 0;
}
「Bob Smith」と入力すると、cin を 2 回呼び出しても、入力は 1 回だけです。ただし、"Bob" と "Smith" の両方が文字列 str1 と str2 に取り込まれていることがわかります。
したがって、cin が Bob と Smith の間のスペースに達すると、string fullname の入力を停止すると結論付けることができます。cin の次の呼び出しでは、バッファーにはまだ "Smith" が含まれているため、ユーザーからさらに入力を受け取る代わりに、変数の給与に "Smith" を入力しようとします。明らかに、これはあなたがしたいことではありません。cin を使用するたびに前にフラッシュを呼び出して cin で無視してバッファーを消去するか、代わりにロジックを修正して getline を使用して、スペースを含む完全な名前を取得することができます。
問題を解決するには、cin >> の代わりに getline を使用するだけなので、次の行を置き換えます。
cin >> fullname;
これとともに:
getline(cin,fullname,'\n');
次に、while ループを使用して一連のアクションを特定の回数実行しています。これは通常、for ループを使用するものです。
余談ですが、デバッグに役立つ小さな入力検証ループを記述したり、無効な入力を変数に入れようとすることを回避したりすることもできます ("Smith" を浮動小数点数にするなど)。このようなものはうまくいくかもしれません:
for(;;)
{
if(cin >> salary)
break;
cin.clear();
cin.ignore(INT_MAX,'\n');
}
cin は値を返すため、if ステートメントで使用できることに注意してください。有効な入力を取得すると、true が返されます。そうでない場合は false を返します。より明確にするために、if ステートメントを使用せずに通常の cin 呼び出しを使用して、cin.good() をチェックすることもできます。これは基本的に同じ正味の効果になります。Visual Studio を使用しておらず、INT_MAX に関するエラーが発生した場合は、解決するために #include limits.h が必要になる場合があります。