使用ungetc统计stdin长度分配内存是否可行?为何代码运行异常?
问题解答
错误原因
- 核心逻辑错误:你的循环流程每次读取第一个字符后立刻用
ungetc放回输入流最前端,下一次fgetc读取到的还是你刚放回的同一个字符,永远无法推进到输入流的后续字符,必然进入死循环,和你观察到的一直输出第一个字符q的现象完全吻合。 - 对
ungetc的特性认知错误:C语言标准仅保证ungetc支持至少1个字符的回退缓冲,超过1个字符的回退行为由编译器实现定义,不存在跨平台通用性。
方案可行性判断
先统计输入长度再分配内存的需求是可行的,但你当前基于反复回退字符的实现思路完全不可用。
正确实现思路
两种工业界常用方案可选:
- 动态扩容方案(最通用):
初始化一个初始大小的数组(比如64字节),每读取一个字符存入数组,当剩余空间不足时调用realloc将数组扩容一倍,直到读取到EOF或换行符为止,无需提前统计长度。
示例代码片段:
#include <stdio.h> #include <stdlib.h> int main() { size_t buf_size = 64, len = 0; char *buf = malloc(buf_size); int ch; if (!buf) { perror("malloc failed"); return 1; } while ((ch = fgetc(stdin)) != EOF && ch != '\n') { if (len + 1 >= buf_size) { buf_size *= 2; char *tmp = realloc(buf, buf_size); if (!tmp) { free(buf); perror("realloc failed"); return 1; } buf = tmp; } buf[len++] = ch; } buf[len] = '\0'; printf("输入内容:%s,长度:%zu\n", buf, len); free(buf); return 0; }
- 临时缓存方案:
如果一定要提前统计长度,可以将第一轮读取的所有字符存入一个临时链表或者固定大小的临时缓冲,统计完长度后分配内存,再从临时缓冲中拷贝数据,不需要操作输入流回退。
内容的提问来源于stack exchange,提问作者erugersauzu
相关产品推荐
相关产品推荐

