题
我有个不好的感觉,这个问题的答案是"没有",但是我想把这个存在的情况下任何人有任何聪明的想法。
我有一个设定出程序,采取一个复杂的数据结构和打印在一个文本的格式。他们有原型,如:
void print_mystruct(struct mystruct *s, FILE *stream)
我写这种方式让我可以得到高效、缓冲输出的终端,一个文件,该网络等。
不幸的是,有没有办法,我知道的,使用标准C99,我可以使用这些同样的程序,建立一个字符串中的存储器。
所以我的问题是:
- 是否有任何聪明的办法,我可以有效地使用fputs(),函数()等。以输出到一串?
- 如果没有,是否有更好的范例,可以有效地做到两个缓冲输出的文件和串建设?好的,我能想到的是要有我自己的结构有虚表(代替一个文件*).该虚表将有一个输出功能,要么添加到一串或呼叫fwrite.但后来我不得不创建printf包装。
任何其它巧妙的想法?
编辑:我们发现, fmemopen()
是的一部分POSIX.1-2008(参见: fmemopen()),但是没有得到广泛的支持,至少根据GNU libc平。
解决方案
有没有便携式的方式这样做。glibc系统(linux)有 open_memstream/fmemopen 其它系统可能没有的东西喜欢它。
便携式的方式是编写文件并阅读它回到一串。 或者以单独的关切问题。而不是实施
void print_mystruct(struct mystruct *s,FILE *f);
你会如实施
char *mystruct_2_str(struct mystruct *s);
动态分配string(或通过在一个缓冲区)、格式给一串与标准字符串职能(snprintf等)。 和呼叫者决定是否编写这一文件*
其他提示
如果你不关心寻求在该文件中,有一个便携式(所有较早的POSIX目标)的方式获得相同的效果 fmemopen
, 但这是相当昂贵。做一个管道和一个新的分离线程,以及 fdopen
写入结束的管在调线。新的螺纹然后读读端的管道和投入的数据进入串的缓冲区。有新的线返回时,它得到EOF从管道;因为它是分离的,没有清理做。
当然,没有什么神奇的有关文件的结构,虽然我不知道的任何建造在图书馆的功能以创造一个从一串的缓冲区。这里至少有一个版本的定义。
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
你可以制造一些结构上你自己从一串的缓冲器,并通过它向你的功能,并且创造一个撕裂下来的功能,可以释放的记忆。
问题是,这CRT图书馆的电话你能用上你的版本吗?显然,任何参考文件,名称将失败,因为没有一个。但你或许可以使用的功能等fwrite和fread和fseek,这将可操作的指针,以及分配更多的空间,如果有必要的。
#include <stdio.h>
#include <stdlib.h>
char* file_to_string(FILE *f, int *len) {
if (fseek(f, 0, SEEK_END)) handle_error();
int buflen = ftell(f);
if (len) *len = buflen;
char *buf = malloc(buflen + 1);
buf[buflen] = '\0';
rewind(f);
size_t readlen = fread(buf, 1, buflen, f);
if (readlen != buflen) handle_error();
// in particular, note readlen might not equal buflen in the face of text-mode
// conversions, but tmpfile() indicates binary-mode, so doesn't affect this
// case
return buf;
}
int main() {
FILE *temp = tmpfile();
// use FILE interface
fputs("written to temporary file\n", temp);
char *s = file_to_string(temp, NULL);
// now you have contents as a string
free(s);
// can also rewind the FILE and process it incrementally, etc.
return 0;
}