web-dev-qa-db-ja.com

getline()は、いくつかの入力の後に使用すると機能しません

可能性のある複製:
getline()のヘルプが必要

getline()は、一部の入力の後に使用すると機能しません。

_#include<iostream>
using namespace std;

main()
{
string date,time;
char journal[23];


cout<<"Date:\t";
cin>>date;
cout<<"Time:\t";
cin>>time;

cout<<"Journal Entry:\t";
cin.getline(journal,23);


cout<<endl;
system("pause");
}
_

ここでは、入力の上でgetline()を使用するかのように、機能します。

_cout<<"Journal Entry:\t";
cin.getline(journal,23);
cout<<"Date:\t";
cin>>date;
cout<<"Time:\t";
cin>>time;
_

その理由は何でしょうか?

(n-1)文字が抽出されるか、区切り文字が見つかる(このパラメーターが指定されている場合はdelim、それ以外の場合は '\ n')まで、文字が抽出されます。入力シーケンスでファイルの終わりに達した場合、または入力操作中にエラーが発生した場合も、抽出は停止します。

cin.getline()が入力から読み取る場合、入力ストリームには改行文字が残っているため、c文字列は読み取られません。 cin.ignore()を呼び出す前にgetline()を使用してください。

cout<<"Journal Entry:\t";
cin.ignore();
cin.getline(journal,23);
34
P.P.

@DavidHammenが言ったことに追加してください:

抽出操作では、ストリームに末尾の_'\n'_文字が残ります。一方、istream::getline()はそれを破棄します。そのため、抽出演算子の後にgetlineを呼び出すと、_'\n'_が最初の文字になり、そこですぐに読み取りを停止します。

これをgetline呼び出し抽出の前に置きます:

cin.ignore()

入力を取得するより堅牢な方法は次のようなものです。

_while (true) {

    cout<<"Time:\t";
    if (cin>>time) {
        cin.ignore();  // discard the trailing '\n'
        break;
    } else {
        // ignore everything or to the first '\n', whichever comes first
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cin.clear();  // clear the error flags
        cout << "Invalid input, try again.\n";
    }
}
_
6
jrok

ストリームのステータスをチェックしていません。 std::cinストリーム抽出演算子(operator>>)は失敗する可能性があります。その場合、ストリームは「不良」としてマークされます(failbitbadbit、またはeofbitが設定されます)。 「不良」になると、ステータスをクリアしない限り、そのストリームに対する後続のすべてのストリーム抽出は失敗します。

偏執的なプログラマーになることを学びましょう。これらのフォーマットされた入力操作のステータスを常に確認してください。たとえば、例外をスローしたり、エラーメッセージを出力して終了したりできます。あなたがすべきでないことの一つは、それがうまくいったと単純に仮定することです。

2
David Hammen