ungetc
来自 cppreference.com
定义于头文件 <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 函数 (p: 243)
- 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++ 文档 适用于 ungetc
|