5

このプログラムを作成しました。ユーザーの住所、名前、仕事を取得します。次に、すべてを 1 つの文字列にまとめて、その文字列を出力します。(これを行うより良い方法があることは知っています)

char str[600];
char adrs[200];
char name[10];
char wrk[200];
cout<<"Enter your name and press ENTER: ";
cin.getline(name,10);
cout<<"\nEnter your adress and press ENTER:";
cin.getline(adrs,200);
cout<<"\nEnter your workplace and press ENTER:";
cin.getline(wrk,200);
strcpy(str,"My name is ");
strcat(str,name);
strcat(str,"\nand i live at ");
strcat(str,adrs);
strcat(str, "\nI also work at ");
strcat(str, wrk); strcat(str, "\n\n");
cout<<str<<endl;

ここで10文字を超える名前を書くと、プログラムはユーザーが入力した最初の9文字を期待どおりに受け取りますが、その後はプログラム内の次の文字をすべてスキップし、cin.getline()出力strしてプログラムを終了します。

なぜこれが起こり、どのように修正するのですか?

4

5 に答える 5

8

cin を使用するたびに、改行文字に遭遇するまで、入力されたすべての文字がメモリに保存されます。このメモリ ブロックは、入力バッファと呼ばれます。への最初の呼び出しcin.getline()は、終端の NULL 文字を含む 10 文字の文字列を要求します。しかし、cin は、ユーザーが Enter キーを押すまで、入力した文字を喜んで読み上げます。ユーザーが 9 文字を超えて入力した場合cin、残りの文字は入力バッファーに格納され、後の入力操作で使用されます。たとえば、ユーザーが 15 文字を入力した場合cin.getline()、最初の 9 文字を c-string 配列に格納するための呼び出し。再度呼び出すcin.getline()と、既に入力された入力の残りの部分が引き続き読み取られます。

この問題を解決するには、 を使用cin.ignore()して、この改行文字をスキップする必要があります。C++ ライブラリへのオンライン リファレンスに慣れることを強くお勧めします。私のお気に入りの 2 つはhttp://www.cplusplus.comhttp://www.cppreference.comです。

編集:私の答えを完成させるためにcin.getline()、入力バッファに要求されたよりも多くの文字がある場合に失敗ビットを設定することも追加する必要があります。cin追加の入力操作に使用する前に、呼び出しcin.clear()てフェイル ビットをクリアする必要があります。

于 2012-08-06T20:24:51.927 に答える
3

When a too-long string is read, ios_base::failbit is set for the stream and all subsequent operations against the stream will fail. You need to reset the failure with ios::clear:

if (cin.fail())
    cin.clear();

After the error is cleared you may want to ignore the rest of the line with istream::ignore.

Edit: It took a helpful hint for me to figure out how to use ignore properly. Here's the total solution.

cout<<"Enter your name and press ENTER: ";
cin.getline(name,10);
if (cin.fail())
{
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

I would suggest putting all that code into a function so that you can call it after every getline.

于 2012-08-07T15:06:00.187 に答える
2

cin.getline(name,10);入力から最大 9 文字を読み取り、改行がある場合は早く停止します。これらの 9 文字に改行がない場合、行の残りの部分には触れず、次の呼び出しでgetline行の残りを読み続けます。

入力行の残りを無視したい場合は、代わりに次を使用できます。

cin.get(name, 10);
cin.ignore(INT_MAX, '\n');
于 2012-08-06T20:44:26.503 に答える
1

free 関数は、文字配列よりもはるかに扱いやすい s でstd::getline動作します。std::string特に、std::getline任意の大きな入力行を許可します。

これを試して:

std::string str;
std::string adrs;
std::string name;
std::string wrk;
cout<<"Enter your name and press ENTER: ";
std::getline(std::cin, name);
cout<<"\nEnter your adress and press ENTER:";
std::getline(std::cin, adrs);
...
于 2012-08-06T21:10:09.903 に答える
0

あなたのロジックは健全です。問題は、サイズ 10 の char 配列を宣言すると、実際には文字を配置するための 10 個のスポットが得られず、9 個しか得られないことです。最後のものは、文字列の終わりを示すために予約されています。[ここ][1] は、この問題について詳しく知りたい場合の参照です。

必要な数よりも 1 文字多く宣言するだけです。ストリームをフラッシュする方法、行の残りを無視する方法など、使用できる優れたヒントがたくさんあります。

幸運を!

于 2012-08-06T21:04:31.640 に答える