ungetc
来自cppreference.com
| 在标头 <stdio.h> 定义
|
||
| |
||
若 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 The ungetc function (第 TBD 页)
- C17 标准(ISO/IEC 9899:2018):
- 7.21.7.10 The ungetc function (第 243 页)
- C11 标准(ISO/IEC 9899:2011):
- 7.21.7.10 The ungetc function (第 334 页)
- C99 标准(ISO/IEC 9899:1999):
- 7.19.7.11 The ungetc function (第 300 页)
- C89/C90 标准(ISO/IEC 9899:1990):
- 4.9.7.11 The ungetc function
参阅
| 从文件流获取一个字符 (函数) | |
ungetc 的 C++ 文档
| |