ungetc只能保证一个字节的后推。另一方面,我已经在Windows和Linux上测试了它,它似乎可以使用两个字节。
是否有任何平台(例如任何当前的Unix系统)实际上只需要一个字节?
答案 0 :(得分:6)
C99标准(以及之前的C89标准)毫不含糊地说:
保证了后退的一个特征。如果调用
ungetc
函数太多 在同一个流上的时间,没有介入读取或文件定位操作 流,操作可能会失败。
因此,为了便于携带,你不会假设有多个后退字符。
话虽如此,在MacOS X 10.7.2(Lion)和RHEL 5(Linux,x86 / 64)上,我试过:
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < 4096; i++)
{
int c = i % 16 + 64;
if (ungetc(c, stdin) != c)
{
fprintf(stderr, "Error at count = %d\n", i);
return(1);
}
}
printf("No error up to count = %d\n", i-1);
return(0);
}
我在任何一个平台上都没有错误。相比之下,在Solaris 10(SPARC)上,我在'count = 4'时收到错误。更糟糕的是,在HP-UX 11.00(PA-RISC)和HP-UX 11.23(Itanium)上,我在'count = 1'时遇到了错误 - 认为2是安全的。同样,AIX 6.0在'count = 1'时出错。
因此,AIX和HP-UX仅在输入文件上允许一个字符的回退,该文件没有读取任何数据。这是一个令人讨厌的案件;一旦从文件中读取了一些数据,它们可能会提供更多的回推容量(但是在循环之前在AIX上添加getchar()
的简单测试没有改变回送容量)。
答案 1 :(得分:4)
这里有一些帖子暗示为了scanf
支持2个字符是有道理的。
我不认为这是对的:scanf
只需要一个,这确实是限制的原因。最初的实现(早在70年代中期)支持100,手册有一个注释:将来我们可能决定只支持1,因为scanf需要的全部内容。 See page 3 of the original manual(也许不是原创,但很老。)
为了更加生动地看到scanf只需要1个字符,请考虑%u
scanf
的{{1}}功能代码。
int c;
while isspace(c=getc()) {} // skip white space
unsigned num = 0;
while isdigit(c)
num = num*10 + c-'0',
c = getc();
ungetc(c);
此处只需拨打一次ungetc()
。没有理由scanf
需要一个char全部自己:它可以与用户共享。
答案 2 :(得分:3)
支持2个后推字符的实现可能按顺序执行,而scanf
可以使用ungetc
进行后推,而不需要第二个几乎相同的机制。对于您来说,这对您来说意味着什么,即使两次调用ungetc
似乎都有效,它在所有情况下都可能不可靠 - 例如,如果流上的最后一个操作是fscanf
它必须使用pushback,你可能只有ungetc
个字符。
在任何情况下,依靠拥有多个ungetc
后推字符是不可移植的,所以我强烈建议不要编写需要它的代码...