web-dev-qa-db-ja.com

c ++ getline()が複数回呼び出されたときにコンソールからの入力を待機していません

私は、コンソールからいくつかのユーザー入力パラメーター、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()が呼び出されるまでコードは停止しません。したがって、コンソール出力は次のようになります。

タイトル:カテゴリー:

カーソルがカテゴリの後に表示されます。ここで入力すると、プログラムは年の入力にジャンプし、複数の文字列を入力できなくなります。ここで何が起こっているのですか?

24
user754852

問題は、演算子>>を使用してgetline()の呼び出しを混在させていることです。

演算子>>は先頭の空白を無視したので、行の境界を越えて正しく続くことに注意してください。ただし、入力が正常に取得された後は読み取りを停止するため、末尾の「\ n」文字は飲み込まれません。したがって、>>の後にgetline()を使用すると、注意しない限り(通常、読み取られなかった '\ n'文字を削除するために)、間違った結果が得られます。

トリックは、両方のタイプの入力を使用しないことです。適切なものを選び、それに固執する。

すべての数値(または演算子>>でニースを再生するオブジェクト)の場合は、演算子>>を使用します(文字列は、入出力と対称ではない(つまり、うまく再生されない)唯一の基本的な型です)。

入力に文字列またはgetl​​ine()を必要とするものの組み合わせが含まれている場合は、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);
23
Martin York

入力バッファをフラッシュする必要があります。これはcin.clear(); cin.sync();で実行できます。

16

使用できます

cin.ignore();

または@kernaldが使用を言及したように

cin.clear();
cin.sync();

getline()を使用する前

12
Rika

前述のように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);
4
sehe

ユーザーが前のcinの前の\ nの前にスペースを入力した場合getlineignoreそれ自体では十分ではないため、ignore()だけではなく、このコードを使用する必要があります。たとえば12345\t\nは機能しなくなります。未処理の文字はすべて無視する必要があります。

#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');

これをcingetlineの間で使用します。

1
Farbod Ahmadian

cin.sync(); cin.ignore(の代わりにこれを使用してください。

0
Gurudev

Getline()と入力ストリームを混在させることは、一般的に悪いことです。ストリームを使用して残ったダーティバッファーを手動で処理することは理論的には可能ですが、それは絶対に避けなければならない不必要な痛みです。

コンソールライブラリを使用して入力を取得することをお勧めします。これにより、ダーティワークを抽象化できます。

TinyConをご覧ください。 getlineおよびstream呼び出しの代わりに静的メソッドtinyConsole :: getLine()を使用するだけで、何度でも使用できます。

ここで情報を見つけることができます: https://sourceforge.net/projects/tinycon/

0
Unix-Ninja