ungetc
|
定义于头文件
<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 函数
参考
|
从文件流获取一个字符
(函数) |
|
|
C++ documentation
for
ungetc
|
|