非常教程

C参考手册

文件输入/输出 | File input/output

ungetc

在头文件<stdio.h>中定义

int ungetc(int ch,FILE * stream);

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

流重新定位操作fseekfsetposrewind丢弃效果ungetc

如果ungetc在没有插入读取或重新定位的情况下多次调用,则可能会失败(换句话说,保证大小为1的推回缓冲区,但是任何较大的缓冲区都是实现定义的)。如果ungetc执行了多个成功操作,则读取操作将按照相反的顺序检索后退字符ungetc

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

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

成功调用ungetc二进制流将流位置指示符递减1(如果流位置指示符为零,则行为不确定)。

ungetc在文本流上的成功调用以未指定的方式修改流位置指示符,但保证在用读取操作检索到所有后推字符后,流位置指示符等于其之前的值ungetc

参数

CH

-

字符被压入输入流缓冲区

-

文件流将字符放回

返回值

成功则返回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) {
    if(*fmt == '%') {
        int c;
        switch(*++fmt) {
            case 'u': while(isspace(c=getc(s))) {} // skip leading white space
                      unsigned int num = 0;
                      while(isdigit(c)) {
                          num = num*10 + c-'0';
                          c = getc(s);
                      }
                      printf("%%u scanned %u\n", num);
                      ungetc(c, s); // reprocess the non-digit
            case 'c': c = getc(s);
                      printf("%%c scanned '%c'\n", c);
        }
    } 
}
 
int main(void)
{
    FILE* f = fopen("input.txt", "w+");
    fputs("123x", f);
    rewind(f); 
    demo_scanf("%u%c", f);
    fclose(f);
}

输出:

%u scanned 123
%c scanned 'x'

参考

  • C11标准(ISO / IEC 9899:2011):
    • 7.21.7.10 ungetc函数(p:334)
  • C99标准(ISO / IEC 9899:1999):
    • 7.19.7.11 ungetc函数(p:300)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 4.9.7.11 ungetc函数
C

C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。