web-dev-qa-db-ja.com

文字列クラスを使用してスペースが入力された場合のcinの問題

私は次のコードを持っています:

main.cpp

#include <iostream>
#include <string>

using namespace std;

string name;
string age;

int main() {
    cout <<"Name: ";
    cin >> name;
    cout << endl;
    cout <<"Age: ";
    cin >> age;
    cout << endl;
    cout << "Your name is " << name << ", and you are " << age << " years old."  << endl;
    cout << "Press enter to close this application" << endl;
    getchar();
    return 0;
}

名前の入力にスペースを入れると名前を入力する機会が得られないことに気づき、スペースの後のエントリは年齢として表示されます。これが初心者の間違いである場合、私はお詫び申し上げます。私は以前にJavaをプログラムしていて、自分のニーズにより適しているため、C++に切り替えたいと思いました。また、おそらくあなたの基準に合わないコードをフォーマットします。必要に応じて修正してください。

Screenshot of console

また、別のエラーにも気づきました。Javaで実際に問題が発生したことはありません。処理が終了したときに即座に終了しないようにする方法がわかりません。 「system。( "pause");を使用できると聞いたが、使用しないように指示された。何を使用するのか本当に混乱している。getchar();を使用すると聞いたが、何もしないようです。

C++に関しては、私は完全な初心者なので、どんな助けでも大歓迎です。

10
dead beef

以下は、プログラムを実行したときに入力バッファで何が起こっているかです。

_std::cin >> name;
_

入力を待っています。 「Ryan Cleary」と入力してEnterキーを押すと、入力バッファーには次のものが含まれます。

_Ryan Cleary\n
_

これでcinは入力を通常どおり読み取り、空白で停止し、次のようにバッファーを残します。

_ Cleary\n
_

Ryanの読み取り後に停止するため、開始スペースに注意してください。最初の変数にはRyanが含まれています。ただし、フルネームが必要な場合は、 _std::getline_ を使用します。空白だけでなく改行まで読み込まれます。とにかく、続けて:

_std::cin >> age;
_

今、あなたは別の入力を得ています。しかし、すでに何かがそこにあります。読み取りを開始できるまで空白をスキップし、バッファを次のように残します。

_\n
_

2番目の変数は、テキストClearyを取得します。改行がバッファに残っていることに注意してください。これにより、2番目の部分に移動します。常に機能するようにsystem ("pause");を置き換えるのは注意が必要です。あなたの最善の策は、通常、完璧ではないソリューションで生活することです、または私がやりたいように、それが言っていることを正確に実行することが保証されていないもの:

_std::cin.get(); //this consumes the left over newline and exits without waiting
_

cin.get() は機能しませんでした。これはどう:

_std::cin.get(); //consume left over newline
std::cin.get(); //wait
_

これは完全に機能しますが、改行が残っていない場所にコピーアンドペーストするとどうなるでしょうか。 Enterキーを2回押す必要があります。

解決策は、改行(およびその他すべて)を消去してから待機することです。これが cin.sync() の目的です。ただし、「メモ」セクションで見られるように、言うようにバッファーをクリアすることは保証されていないため、コンパイラーがクリアしないことを選択した場合、バッファーを使用できません。しかし、私にとってはそれは正確にそれを行い、解決策を残します:

_std::cin.sync(); //clear buffer
std::cin.get(); //wait
_

system("pause");の主な悪い点は、他の人のコンピュータでどのプログラムが実行されるかがわからないことです。それらは_pause.exe_を変更したり、最初に見つかったものを置いたりすることができ、あなたは知る方法がありません。これは、anyプログラムである可能性があるため、コンピュータを破壊する可能性があります。

15
chris

cin.getline を試してみてください。そうすれば、ストリームは最初の改行文字まで読み取られます。

さて、一部の人々が指摘したように悪いアドバイス。 std :: getline を使用して行全体を読み取ることができます。ここでも、通知がない限り、区切り文字は改行です。 cinから読み取るには、最初のパラメーターとして(および2番目のストリングとして)文字列を渡します。

std::string str;
std::getline(cin, str); // to read until the end of line

std::getline(cin, str, ' '); // to read until a space character, for instance

(もちろん、std::行の一部です。これは、std名前空間を使用していることをコンパイラにすでに通知しているためです)

7
Bruno Brant