web-dev-qa-db-ja.com

stdinバッファを覗く方法はありますか?

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

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

./a.out
こんにちは
こんにちは、左は10です

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

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

[〜#〜]編集[〜#〜]
より良い例は次のとおりです。

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

「at.ct」を入力すると、「データ」(ct\n)改行だけでなく、stdinのままにしておきます。

21
Mike

移植性がありますが、getchar()を使用して入力ストリーム内の次の文字を取得し、ungetc()を使用してプッシュバックできます。これにより、文字がストリームから削除されていないかのような状態になります。 。

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

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

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

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

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

配列の内容はいつでも不確定です。

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

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

11
Daniel Fischer

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

char buffer[BUFSIZ];

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

getchar();

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

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

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

配列の内容はいつでも不確定です。

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

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

4
effeffe

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

4
nullpotent