C语言深度解析 ungetc

C语言深度解析 ungetc基础定义与陷阱 int ungetc int c FILE stream 核心功能 将字符 c 回退到输入流 stream 后续读取顺序为后进先出隐藏规则 仅保证至少 1 次成功回退 C99 标准 多次回退后读取顺序 ungetc

大家好,欢迎来到IT知识分享网。

基础定义与陷阱

int ungetc(int c, FILE *stream);
  • 核心功能:将字符c回退到输入流stream,后续读取顺序为后进先出
  • 隐藏规则
  • 仅保证至少1次成功回退(C99标准)
  • 多次回退后读取顺序:
  • ungetc(‘A’, fp); ungetc(‘B’, fp); → 读取顺序为B→A
  • 文件结束符EOF处理:调用ungetc后清除流的EOF状态

实战场景

场景1:动态类型解析器

void parse_value(FILE *fp) { int c = fgetc(fp); if (isdigit(c)) { ungetc(c, fp); // 回退数字字符 int num; fscanf(fp, "%d", &num); printf("Parsed number: %d\n", num); } else if (c == '"') { parse_string(fp); // 进入字符串解析 } else { ungetc(c, fp); // 回退未知字符 parse_identifier(fp); } } 

设计亮点:通过预读+回退实现多类型解析分支


场景2:二进制流标记检测

int find_magic(FILE *fp, const char *magic) { int match = 1; long pos = ftell(fp); for (const char *p = magic; *p; ++p) { int c = fgetc(fp); if (c != *p) { match = 0; // 关键点:精准回退已读取字节 fseek(fp, pos, SEEK_SET); break; } } return match; } 

对比优势:相比单纯使用ungetc,fseek+ftell组合更适合二进制流回溯


高级技巧:缓冲区冲突测试

char buf; FILE *fp = fopen("test.txt", "r"); setvbuf(fp, buf, _IOFBF, sizeof(buf)); // 设置全缓冲 int c1 = fgetc(fp); // 触发缓冲填充 ungetc('X', fp); // 向缓冲区插入字符 // 验证缓冲区修改 printf("Current buffer: ["); for (int i=0; i<sizeof(buf); i++) { printf("%c ", (buf[i] == 0) ? '_' : buf[i]); } printf("]\n"); 

运行结果:缓冲区首字符被修改为X,展示库函数内部缓冲区操作机制


流状态劫持:动态修改输入内容

// 运行时替换输入流中的敏感词 void filter_swear_words(FILE *fp) { int c; while ((c = fgetc(fp)) != EOF) { if (c == 'F') { // 检测敏感词起始字符 ungetc('?', fp); // 替换为无害字符 ungetc('?', fp); // 双写保持字符数一致 break; } putchar(c); } } 

独特价值
实现「字符级输入流动态重写」,适用于实时过滤系统(如聊天室脏话过滤),相比传统先读后处理的方案节省内存。


跨平台差异警告表

行为

Linux (glibc)

Windows (MSVCRT)

最大回退次数

4 (默认缓冲大小)

1 (严格遵守C99)

回退EOF

允许

导致未定义行为

混合fseek后的有效性

失效

部分版本保留回退字符

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/175770.html

(0)
上一篇 2025-04-09 12:10
下一篇 2025-04-09 12:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信