24

stdinこれは、デフォルトではバッファリングされた入力であることがわかっています。その証拠は、次のstdinような「データを残す」メカニズムのいずれかを使用していることscanf()です。

int main()
{
    char c[10] = {'\0'};
    scanf("%9s", c);
    printf("%s, and left is: %d\n", c, getchar());
    return 0;
}

./a.out
hello
hello、左は10です

10もちろん改行です...

私はいつも興味がありますが、そこにある可能性のstdinあるものを削除せずにバッファを「覗く」方法はありますか?

編集
より良い例は次のとおりです。

scanf("%9[^.]", c);

「at.ct」を入力すると、改行だけでなく 「data」( ct\n)が残ります。stdin

4

3 に答える 3

13

移植性のある方法として、入力ストリーム内の次の文字をで取得し、getchar()それをで押し戻すことができungetc()ます。これにより、文字がストリームから削除されていないかのような状態になります。

この関数は、で指定された(に変換された)文字を、streamが指す入力ストリームにungetcプッシュバックします。プッシュバックされた文字は、そのストリームでの後続の読み取りによって、プッシュの逆の順序で返されます。cunsigned char

プッシュバックの1文字のみが標準で保証されていますが、通常はさらにプッシュバックできます。

他の回答で述べたように、それぞれ。そこにあるコメントは、実際には、独自のバッファにを提供すれば、ほぼ確実にバッファを覗くことができますが、setvbuf問題がないわけではありません。

がnullポインターでない場合は、関数bufによって割り当てられたバッファーの代わりに、それが指す配列を使用できます。setvbuf

そのため、提供されたバッファーがまったく使用されない可能性があります。

アレイの内容はいつでも不確定です。

つまり、バッファの内容が実際の入力を反映しているという保証はありません(また、自動保存期間がある場合は、バッファの未定義動作を使用することになります)。

ただし、実際には、主な問題は、バッファ内のバッファリングされた入力のまだ消費されていない部分がどこから始まり、どこで終わるかを見つけることです。

于 2013-01-21T17:20:45.067 に答える
4

on stdinを使用して独自のバッファを設定し、setvbuf必要なときにいつでもそこを覗くことができます。

于 2012-12-21T16:36:15.063 に答える
4

バッファを変更せずに確認したい場合は、アクセス可能な配列を使用stdinして、で別のバッファを使用するように指示setbufできます。

char buffer[BUFSIZ];

if (setbuf(stdin, buffer) != 0)
  // error

getchar();

printf("%15s\n", buffer);

これにより、以上のものを見ることungetcができますが、ポータブルな方法でさらに先に進むことはできないと思います。

setvbuf実際にはこれは合法ですが、標準に対しては正しくありません。 (setbuf同じ動作をします)について引用します。

アレイの内容はいつでも不確定です。

したがって、完全な移植性と標準への準拠を求めている場合、これは必要なものではありませんが、バッファに期待されるものが含まれていてはならない理由は想像できません。しかし、それは私のコンピューターでは動作するようです。

に少なくともBUFSIZ文字の配列を提供するsetbuf必要があり、その前にストリームに対してI/O操作を実行してはならないことに注意してください。より柔軟性が必要な場合は、をご覧くださいsetvbuf

于 2012-12-21T17:26:48.447 に答える