1. ホーム
  2. c++

[解決済み] なぜ2回エンターキーを押さなければならないのですか?

2022-02-16 07:25:27

質問事項

私のプログラムでは、ある場所に到達したときに、なぜか 入力 を2回送信するようにしました。入力をスキップしないようにclearを追加し、バッファに余分な文字を残さないようにignore()を追加しました。入力したら改行されたので 入力 もう一度入力すると、入力され、問題なくプログラムが継続されるのですが、なぜでしょうか?以下はコードの断片です。

    cin.ignore();
    cout << "Enter Student Major (ex. COSC): ";
    cin.getline(student.major, 6);

    for(int i = 0; i < sizeof(student.major); i++)
        student.major[i] = toupper(student.major[i]);

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

何かご意見はありますか?

解決方法は?

を投げすぎているような気がします。 cin.ignore() なぜそれが必要なのか、どのようなときにそれを配置するのか、よくわからないままです。

よくある状況として、以下の2つがあります。 cin.ignore() は、入力を正しく動作させるために必要です。

  1. フォーマットされた入力とフォーマットされていない入力を混在させる場合。
  2. フォーマットされた入力のエラーから回復するため。

どちらの場合も、入力バッファから偽の文字を取り除きたいのです。そのような文字がない場合(おそらくあなたのプログラムではそうなっているのでしょう)。 cin.ignore() 結局のところ、あなたはいくつかの文字を無視するように頼んだのですから、ちくしょう、その命令に従うでしょう。

(ただし ignore() は一文字だけで、それが何であれ、改行が見つかるまでは実行が一時停止されるからです。 cin はラインバッファリングされており、改行を受け取るまで新しい入力は検査されません)

ケース1

cin.ignore() を実行する場合、しばしば呼び出しが必要になります。 非整形入力 操作(例えば getline を実行した後に 書式付き入力 操作(つまり >> 演算子)を使用します。

このようなことが起こるのは >> 演算子は入力バッファに改行を残します。これは、フォーマットされた入力操作だけを行う場合は問題ありませんが(デフォルトでは、入力を解釈しようとする前にすべてのホワイトスペースをスキップします)、その後にフォーマットされていない入力を行う場合は問題です。 getline はデフォルトで改行を見つけるまで読むので、"spurious newline"が残っていると、すぐに読み込みを中止してしまうのです。

そこで、ここでは通常 cin.ignore(...) を呼び出して、連続した最後のフォーマットされた入力操作の直後に改行を取り除き、入力バッファが空であることを保証します。その後に getline バッファを空にしたことがわかるので、安心して直接実行できます。

それは、かえって悪いことで、それを置くために 前に いずれかの getline につながるコードパスがあるかもしれないので、あなたのコードでやっているように getline 入力バッファがクリーンな状態であるため ignore の呼び出しはブロックされます。

ケース2

いつ istream フォーマットされた入力操作でエラーが発生した場合、バッファに "bad" という文字が残ってしまうので、操作をやり直すと違反者が残っているため、延々とスタックしてしまいます。通常の clear()/ignore() というイディオムが登場し、入力バッファから問題のある行を丸ごと削除してくれます。

ここでも clear()/ignore() のシーケンスがランダムに表示され、フォーマットされた入力操作で入力エラーが発生した後(ストリームのfailbitが設定される)、初めて表示されます。


さて、このようなケースは別として、一般的には cin.ignore() (実際に文字をスキップしたい場合を除き)ランダムにばら撒くのはやめましょう"念のため"。