2011-10-16 9 views
15

コンソールから2つの文字列、2つのint、および2つのユーザー入力パラメーターを取得しようとしています。私が使用しようとしている関連するコードはこれです:複数回呼び出したときにgetline()がコンソールからの入力を待っていません

#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から待っているときしかし、コードが第二のgetline()の呼び出しまでは停止しません。 。したがって、コンソール出力は次のようになります。

タイトル:カテゴリー:

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

+0

を再現することはできませんを使用する前に、

cin.ignore(); 

かなど@kernald言及した使用

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

を使用することができます。本当の完全なコードを投稿してください。私はあなたの問題がどこかにあると確信しています。また、フォーマットされた入力と 'getline()'を混在させないでください。 –

+0

@KerrekSB:それらを混ぜることは悪いスタイルの症状であることに同意しますが、それらを混ぜないという客観的な理由は何ですか?本当にそれらを混ぜることは完全に有効だと思います。 – sehe

+0

@sehe:フォーマットされた抽出は改行を消費しないので、前の行のすべてをすでに処理したと考えて 'getline()'を実行すると、予期しない結果を得るのは非常に簡単です。私はそれが不可能だと言っているわけではありませんが、それはしばしばロジックを読みとって維持することを非常に困難にします。 –

答えて

16

問題は、あなたがオペレータの使用>>とのgetline()への呼び出しを混合されています。

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

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

すべての数値(または演算子>>で素敵なオブジェクト)の場合は、演算子>>を使用します(注記文字列は入力/出力と対称ではない(つまりうまく再生できません)) 。

入力にgetline()が必要な文字列またはstuffの組み合わせが含まれている場合は、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); 
7

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

3

言及使用、適切なエラー処理として利用cin.clear()

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); 
+1

ありがとうございます。このコードは、cin.clear()とcin.sync()の両方が使用されている場合にのみ機能します。 – user754852

+0

>>演算子をgetline()メソッドと組み合わせる最も簡単な方法は、getlineへの呼び出しの前にcin.ignore()を入力して、前の入力からの改行文字が入力バッファからすべて削除されるようにすることです。 –

0

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

コンソールライブラリを使用して入力を取得する方がよいでしょう。この方法でダーティー作業を抽象化することができます。

TinyConをご覧ください。あなたは、getlineとストリーム呼び出しの代わりにstaticメソッドtinyConsole :: getLine()を使うことができます。そして、あなたは望むように何度も使うことができます。

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

4

あなたはgetl​​ineの()

関連する問題