ungetc:推回的字节数

问题描述 投票:0回答:3

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

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

c unix stdio ungetc
3个回答
9
投票

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”处收到错误,在 Solaris 11.3 上也是如此。更糟糕的是,在 HP-UX 11.00 (PA-RISC)、HP-UX 11.23 (Itanium) 和 HP-UX 11.31 (Itanium) 上,我在“count = 1”处收到错误 - 违背了 2 是安全的理论。同样,AIX 6.0(和 7.2)在“count = 1”处给出错误。

总结

  • Linux:大(4 KiB)
  • MacOS X:大(4 KiB)
  • 索拉里斯:4
  • HP-UX:1
  • AIX:1

因此,AIX 和 HP-UX 只允许在尚未读取任何数据的输入文件上推回一个字符。这是一个令人厌恶的案例;一旦从文件中读取了一些数据,它们可能会提供更多的推回能力(但在 AIX 上进行的简单测试在循环之前添加

getchar()
并没有改变推回能力)。


5
投票

这里有一些帖子建议为了

scanf
支持 2 个字符是有意义的。

我认为这是不对的:

scanf
只需要一个,这确实是限制的原因。最初的实现(早在 70 年代中期)支持 100,并且手册中有一个注释:将来我们可能决定仅支持 1,因为这就是 scanf 所需要的。 请参阅原始手册的第 3 页(也许不是原创,但相当旧了。)

要更生动地看到 scanf 只需要 1 个字符,请将此代码视为

%u
scanf
功能。

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
没有理由需要一个单独的字符:它可以与用户共享。


4
投票

支持 2 个推回字符的实现可能会这样做,以便

scanf
可以使用
ungetc
进行推回,而不需要第二个几乎相同的机制。对于应用程序程序员来说,这意味着即使调用
ungetc
两次似乎有效,但它可能并不在所有情况下都可靠 - 例如,如果流上的最后一个操作是
fscanf
并且它必须使用推回,您可能只能
ungetc
一个字符。

无论如何,依赖于具有多个

ungetc
推回字符是不可移植的,所以我强烈建议不要编写需要它的代码......

© www.soinside.com 2019 - 2024. All rights reserved.