C凯撒密码命令行工具:如何临时存储管道输入以复用?
问题描述
我正在开发一款coreutils风格的C语言凯撒移位加密程序,目前已支持读取指定文件并输出移位结果,现在要添加管道输入支持(类似wc命令的行为):
- 指定1-26范围内密钥时:用
getchar()读取管道输入,移位后putchar()输出,这个逻辑很简单。 - 未指定密钥时:需要用1-26所有密钥遍历输入并输出每一种移位结果。处理文件时可以用
rewind()重复读取,但管道输入无法直接重复读取。
我目前想到两种临时存储方案:
- 动态扩容缓冲区:把管道输入全部读到内存里,之后循环遍历缓冲区生成各密钥的结果,但担心大文件会耗尽内存。
- 临时文件:把管道输入写入临时文件,之后像普通文件一样用
rewind()重复读取。
想请教有没有更优的方案,或者应该优先选择哪一种?
相关示例
管道指定密钥的使用场景:
$ echo "pants" | ccipher --key 7 whuaz
读取文件遍历所有密钥的场景:
$ cat input pants $ ccipher input qbout rcpvu ...(省略后续结果)
当前处理文件遍历密钥的核心代码:
void allKeys(FILE** file) { long key; char c; for (key = 1; key < 26; key++) { while ((c = fgetc(*file)) != EOF) { rotateChar((char)c, key); } rewind(*file); } fclose(*file); }
解决方案建议
优先选择临时文件方案,理由如下:
- 内存友好:不管输入多大(哪怕是几个GB的数据流),都不会耗尽内存,完全符合coreutils工具处理任意大小输入的设计原则。
- 实现简单:可以直接复用你现有的
allKeys逻辑,只需要把管道输入先写入临时文件,再把临时文件的FILE*传入该函数即可,几乎不需要修改核心逻辑。 - 兼容性好:临时文件的处理在所有POSIX系统上都有标准接口(比如
mkstemp()),不会有平台兼容性问题。
至于动态扩容缓冲区,只适合输入数据量较小的场景,一旦遇到大输入就会触发OOM,不符合coreutils工具的健壮性要求,不推荐作为默认方案。
另外可以考虑一个进阶思路:一次读取、同时生成所有26种结果。每读取一个字符,直接计算它在1-26所有密钥下的移位结果,分别缓存到26个输出缓冲区(或按顺序输出到对应结果块)。这种方式不需要存储原始输入,内存占用只和26份输出的当前行长度有关,但实现复杂度会高一些——需要维护26个独立的输出状态,比如换行符处理、结果的顺序拼接等。
综合来看,临时文件方案的性价比最高:实现成本低、健壮性强,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者Seth Buchanan
相关产品推荐
相关产品推荐

