有没有办法偷看stdin缓冲区?

我们知道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
你好
你好,左边是10

10当然是新行……

我一直很好奇,有没有办法“偷看” stdin缓冲区而不删除那里可能存在的东西?

编辑
一个更好的例子可能是:

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

输入“at.ct”,现在我在stdin留下了“数据”( ct\n ),而不仅仅是换行符。

或者,您可以使用getchar()获取输入流中的下一个字符,然后使用ungetc()将其推回,这会导致状态,就好像该字符未从流中删除一样。

ungetc函数将c指定的字符(转换为unsigned char )推回到stream指向的输入流。 按推送的相反顺序,后续读取该流将返回推回的字符。

标准只保证了一个回击角色,但通常情况下,你可以更多地推回。

正如其他答案所述。 那里的评论,实际上,如果你使用setvbuf提供自己的缓冲区,你几乎可以肯定地查看缓冲区,尽管这不是没有问题:

如果buf不是空指针,则可以使用它指向的数组而不是setvbuf函数分配的缓冲区

这留下了可能根本不使用所提供的缓冲区的可能性。

任何时候数组的内容都是不确定的。

这意味着您无法保证缓冲区的内容反映实际输入(如果它具有自动存储持续时间,如果我们挑剔则使用缓冲区未定义的行为)。

然而,在实践中,主要问题是找出缓冲区中尚未消耗的部分开始的位置和结束位置。

您可以在stdin上使用setvbuf设置自己的缓冲区,并随时查看。

如果你想在不改变它的情况下查看stdin缓冲区,你可以告诉它使用另一个带setbuf缓冲区,使用你可以访问的数组:

 char buffer[BUFSIZ]; if (setbuf(stdin, buffer) != 0) // error getchar(); printf("%15s\n", buffer); 

这让你看到的东西比ungetc更多,但我认为你不能以便携的方式走得更远。

实际上这是合法的,但对于标准来说是不正确的,引用它来讨论setvbufsetbuf具有相同的行为):

任何时候数组的内容都是不确定的。

因此,如果您正在寻找完全可移植性和标准兼容性,那么这不是您所需要的,但我无法想象为什么缓冲区不应包含预期的内容。 但是,它似乎可以在我的电脑上运行。

请注意,您必须为setbuf提供至少BUFSIZ字符的数组,并且您不能在它之前对流执行任何I / O操作。 如果您需要更多灵活性,请查看setvbuf