我有一个简单的C代码片段如下:
#include <stdio.h>
void main() {
FILE *f;
char c;
f = popen("ls", "r");
while ((c = fgetc(f)) != EOF) {
//Some tasks
}
rewind(f);
while ((c = fgetc(f)) != EOF) {
printf("%c", c);
}
fclose(f);
}
我不知道为什么代码没有输出任何内容。看来 rewind() 函数不起作用。请帮忙找出我哪里错了。谢谢。
rewind
相当于 fseek(stream, 0L, SEEK_SET)
并且 fseek
仅在文件上合法,在流上不合法(管道就是这种情况)。
检查
errno
之后的 rewind
应该是
EBADF 指定的流不是可查找流。
正如其他人已经说过的,你不能重绕管道。没有说的是一个好的解决方案可能是什么。幸运的是,答案很简单,至少在 UNIX 上,使用 memstream 将数据作为流缓冲到内存中,您可以回滚。
TL;博士FILE *mem = open_memstream(NULL, NULL);
while ((c = fgetc(f)) != EOF) {
fputc(c, mem);
//...Some tasks...
}
rewind(mem);
关于内存流它长期以来一直是 POSIX 标准的一部分,并且适用于所有现代 UNIX 系统。实现包含在基于 GNU 和 BSD 的系统(例如 Debian 和 MacOS)的 C 库中。
替代品
手动将数据读入数组是一种合理的选择,但在某些需要流的情况下可能不可行,例如使用某些库(例如 libpng)或编程框架(例如 lex 解析)。此外,根据内存的分配方式,数组的编码可能会更复杂。
完整代码
#include <stdio.h>
#include <err.h> /* For err() */
void main() {
FILE *f, *mem;
int c;
f = popen("ls", "r");
mem = open_memstream(NULL, NULL);
if (mem == NULL)
err(EXIT_FAILURE, "open_memstream");
while ((c = fgetc(f)) != EOF) {
fputc(c, mem);
// ... Some tasks ...
}
pclose(f);
rewind(mem);
while ((c = fgetc(mem)) != EOF) {
printf("%c", c);
}
fclose(mem);
}
缺点MSVC 的 open_memstream 的等效项)。