ungetc

ungetc

在头文件中定义
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):