ungetc:pushback的字节数

时间:2011-10-18 23:05:30

标签: c unix stdio ungetc

ungetc只能保证一个字节的后推。另一方面,我已经在Windows和Linux上测试了它,它似乎可以使用两个字节。

是否有任何平台(例如任何当前的Unix系统)实际上只需要一个字节?

3 个答案:

答案 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'时出错。

摘要

  • Linux:big(4 KiB)
  • MaxOS X:大(4 KiB)
  • Solaris:4
  • HP-UX:1
  • AIX: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后推字符是不可移植的,所以我强烈建议不要编写需要它的代码...