Namespaces
Variants

ungetc

From cppreference.net
< c ‎ | io
定义于头文件 <stdio.h>
int ungetc ( int ch, FILE * stream ) ;

如果 ch 不等于 EOF ,则将字符 ch (重新解释为 unsigned char )推入与流 stream 关联的输入缓冲区,使得后续从 stream 进行的读取操作将获取该字符。与流关联的外部设备不会被修改。

流重定位操作 fseek fsetpos rewind 会丢弃 ungetc 的效果。

如果多次调用 ungetc 而未进行读取或重定位操作,可能会失败(换言之,保证存在大小为1的回退缓冲区,但更大的缓冲区由实现定义)。若成功执行了多次 ungetc 操作,读取操作将按照与 ungetc 调用相反的顺序获取被回退的字符。

如果 ch 等于 EOF ,则操作失败且流不受影响。

ungetc 的成功调用会清除文件结束状态标志 feof

对二进制流的 ungetc 调用成功时,流位置指示器将递减一(若流位置指示器原为零则行为未定义)。

对文本流成功调用 ungetc 会以未指定的方式修改流位置指示器,但确保在所有被推回的字符通过读取操作检索完毕后,流位置指示器将恢复至调用 ungetc 之前的值。

目录

参数

ch - 要推回输入流缓冲区的字符
stream - 要将字符放回的文件流

返回值

成功时返回 ch

失败时返回 EOF 且给定流保持不变。

注释

推送缓冲区的大小在实践中各不相同,从4k(Linux,MacOS)到小至4(Solaris)或保证的最小值1(HPUX,AIX)。

如果回退的字符与外部字符序列中该位置的现有字符相同,则回退缓冲区的表观大小可能会更大(实现可能只需递减读取文件位置指示器,而无需维护回退缓冲区)。

示例

演示 ungetc 的原始用途:实现 scanf

#include <ctype.h>
#include <stdio.h>
void demo_scanf(const char* fmt, FILE* s)
{
    while (*fmt != '\0')
    {
        if (*fmt == '%')
        {
            int c;
            switch (*++fmt)
            {
                case 'u':
                    while (isspace(c=getc(s))) {}
                    unsigned int num = 0;
                    while (isdigit(c))
                    {
                        num = num*10 + c-'0';
                        c = getc(s);
                    }
                    printf("%%u scanned %u\n", num);
                    ungetc(c, s);
                    break;
                case 'c':
                    c = getc(s);
                    printf("%%c scanned '%c'\n", c);
                    break;
            }
        {
        else
            ++fmt;
    }
}
int main(void)
{
    FILE* f = fopen("input.txt", "w+");
    if (f != NULL)
    {
        fputs("123x", f);
        rewind(f);
        demo_scanf("%u%c", f);
        fclose(f);
    }
    return 0;
}

输出:

%u scanned 123
%c scanned 'x'

参考文献

  • C23 标准 (ISO/IEC 9899:2024):
  • 7.21.7.10 ungetc 函数 (p: TBD)
  • C17 标准 (ISO/IEC 9899:2018):
  • 7.21.7.10 ungetc 函数 (页: 243)
  • C11 标准 (ISO/IEC 9899:2011):
  • 7.21.7.10 ungetc 函数 (p: 334)
  • C99标准(ISO/IEC 9899:1999):
  • 7.19.7.11 ungetc函数(页码:300)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 4.9.7.11 ungetc 函数

参考

从文件流获取一个字符
(函数)