©
Ce document utilise Manuel du site Web PHP chinois Libérer
在头文件<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
二进制流将流位置指示符递减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函数