私は、コンソールからいくつかのユーザー入力パラメーター、2つの文字列、2つのint、およびdoubleを取得しようとしています。私が使用しようとしている関連コードはこれです:
#include <string>
#include <iostream>
using namespace std;
// ...
string inputString;
unsigned int inputUInt;
double inputDouble;
// ...
cout << "Title: ";
getline(cin, inputString);
tempDVD.setTitle(inputString);
cout << "Category: ";
getline(cin, inputString);
tempDVD.setCategory(inputString);
cout << "Duration (minutes): ";
cin >> inputUInt;
tempDVD.setDuration(inputUInt);
cout << "Year: ";
cin >> inputUInt;
tempDVD.setYear(inputUInt);
cout << "Price: $";
cin >> inputDouble;
tempDVD.setPrice(inputDouble);
ただし、プログラムを実行すると、最初のinputStringが入力されるのを待つ代わりに、2番目のgetline()が呼び出されるまでコードは停止しません。したがって、コンソール出力は次のようになります。
タイトル:カテゴリー:
カーソルがカテゴリの後に表示されます。ここで入力すると、プログラムは年の入力にジャンプし、複数の文字列を入力できなくなります。ここで何が起こっているのですか?
問題は、演算子>>を使用してgetline()の呼び出しを混在させていることです。
演算子>>は先頭の空白を無視したので、行の境界を越えて正しく続くことに注意してください。ただし、入力が正常に取得された後は読み取りを停止するため、末尾の「\ n」文字は飲み込まれません。したがって、>>の後にgetline()を使用すると、注意しない限り(通常、読み取られなかった '\ n'文字を削除するために)、間違った結果が得られます。
トリックは、両方のタイプの入力を使用しないことです。適切なものを選び、それに固執する。
すべての数値(または演算子>>でニースを再生するオブジェクト)の場合は、演算子>>を使用します(文字列は、入出力と対称ではない(つまり、うまく再生されない)唯一の基本的な型です)。
入力に文字列またはgetline()を必要とするものの組み合わせが含まれている場合は、getline()のみを使用して、文字列から数値を解析します。
std::getline(std::cin, line);
std::stringstream linestream(line);
int value;
linestream >> value;
// Or if you have boost:
std::getline(std::cin, line);
int value = boost::lexical_cast<int>(line);
入力バッファをフラッシュする必要があります。これはcin.clear(); cin.sync();
で実行できます。
使用できます
cin.ignore();
または@kernaldが使用を言及したように
cin.clear();
cin.sync();
getline()を使用する前
前述のようにcin.clear()
を使用and適切なエラー処理を使用:
cin.clear();
cin.sync();
cout << "Title: ";
if (!getline(cin, inputString)) exit 255;
tempDVD.setTitle(inputString);
cout << "Category: ";
if (!getline(cin, inputString)) exit 255;
tempDVD.setCategory(inputString);
cout << "Duration (minutes): ";
if (!(cin >> inputUInt)) exit 255;
tempDVD.setDuration(inputUInt);
cout << "Year: ";
if (!(cin >> inputUInt)) exit 255;
tempDVD.setYear(inputUInt);
cout << "Price: $";
if (!(cin >> inputDouble)) exit 255;
tempDVD.setPrice(inputDouble);
ユーザーが前のcinの前の\ nの前にスペースを入力した場合getline、ignoreそれ自体では十分ではないため、ignore()だけではなく、このコードを使用する必要があります。たとえば12345\t\nは機能しなくなります。未処理の文字はすべて無視する必要があります。
#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');
これをcinとgetlineの間で使用します。
cin.sync(); cin.ignore(の代わりにこれを使用してください。
Getline()と入力ストリームを混在させることは、一般的に悪いことです。ストリームを使用して残ったダーティバッファーを手動で処理することは理論的には可能ですが、それは絶対に避けなければならない不必要な痛みです。
コンソールライブラリを使用して入力を取得することをお勧めします。これにより、ダーティワークを抽象化できます。
TinyConをご覧ください。 getlineおよびstream呼び出しの代わりに静的メソッドtinyConsole :: getLine()を使用するだけで、何度でも使用できます。
ここで情報を見つけることができます: https://sourceforge.net/projects/tinycon/