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

时间:2012-12-21 16:29:27

标签: c buffer stdin peek

我们知道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”后,现在我在ct\n上留下了“数据”(stdin),而不仅仅是换行符。

3 个答案:

答案 0 :(得分:11)

便携式地,您可以使用getchar()获取输入流中的下一个字符,然后使用ungetc()将其推回,这会产生一种状态,就好像该字符未从该字符中删除流。

  

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

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

正如其他答案所述。那里的评论,在实践中,如果你提供自己的setvbuf缓冲区,你几乎可以肯定地查看缓冲区,虽然这不是没有问题:

  

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

这样就可能根本不使用提供的缓冲区。

  

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

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:4)

如果你想查看stdin缓冲区而不更改它,你可以告诉它使用另一个setbuf的缓冲区,使用你可以访问的数组:

char buffer[BUFSIZ];

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

getchar();

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

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

实际上这是合法的,但标准不正确,引用setvbufsetbuf具有相同的行为):

  

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

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

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