C语言中向标准输入(stdin)推送多个字符的方法
如何向标准输入流(stdin)推送任意数量的字符?
ungetc()确实只保证支持单个字符的回推,C标准并未要求实现支持多个字符的回推操作。要推送任意数量的字符,有两种可靠的解决方案:
1. 自定义带缓冲的输入层
自己实现一个输入缓冲区,所有输入操作都通过这个缓冲区完成。推送字符时先存入缓冲区,读取时优先从缓冲区取数据,缓冲区空了再去读取原始stdin。这种方法完全不受ungetc()的限制,能支持任意数量的推送字符。
示例代码(C语言):
#include <stdio.h> // 自定义回推缓冲区,大小可按需调整 static char push_buf[1024]; static int push_ptr = 0; // 替代标准getchar()的自定义读取函数 int my_getchar(void) { if (push_ptr > 0) { return push_buf[--push_ptr]; } return getchar(); } // 推送单个字符到缓冲区 void push_char(int c) { if (push_ptr < sizeof(push_buf)) { push_buf[push_ptr++] = c; } else { fprintf(stderr, "回推缓冲区已满,无法添加更多字符\n"); } } int main() { // 推送3个'*'字符 push_char('*'); push_char('*'); push_char('*'); // 读取输入并输出 int c; while ((c = my_getchar()) != EOF) { putchar(c); // 会先输出***,再输出原stdin的abc } return 0; }
注意:所有需要读取stdin的地方都要改用my_getchar();如果需要使用fscanf()这类函数,可以封装对应的自定义版本,或者通过平台相关操作替换stdin的文件指针。
2. 重定向stdin到内存流/临时文件
如果能提前获取原stdin的全部内容,可以将推送字符和原内容拼接后,创建一个内存流(或临时文件),再将stdin重定向到这个新流。这种方法适合原stdin内容已知且完整的场景。
示例代码(POSIX平台,使用fmemopen):
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 模拟原stdin的内容"abc" const char* original = "abc"; // 拼接推送字符和原内容 size_t new_len = 3 + strlen(original) + 1; char* new_content = malloc(new_len); if (!new_content) { perror("malloc失败"); return 1; } snprintf(new_content, new_len, "***%s", original); // 创建内存流 FILE* mem_stream = fmemopen(new_content, strlen(new_content), "r"); if (!mem_stream) { perror("fmemopen失败"); free(new_content); return 1; } // 保存原stdin指针,重定向到内存流 FILE* old_stdin = stdin; stdin = mem_stream; // 现在读取stdin就会得到***abc int c; while ((c = getchar()) != EOF) { putchar(c); } // 恢复原stdin并清理资源 stdin = old_stdin; fclose(mem_stream); free(new_content); return 0; }
局限性:如果原stdin是实时输入(比如用户正在终端输入),无法提前获取全部内容,这种方法就不适用。
内容的提问来源于stack exchange,提问作者StaticESC
相关产品推荐
相关产品推荐

