在 C 中,我经常希望以相同的方式处理从文件读取的数据和从字符串数组读取的数据。通常从文件读取用于生产,从字符串读取用于测试。我写了很多这样的代码:
void handle_line(char *line, Things *things) {
...
}
Things *read_from_chars(char *lines[]) {
Things *things = Things_new();
for (int i = 0; lines[i] != NULL; i++) {
handle_line(lines[i], things);
}
return things;
}
Things *read_from_input(FILE *input) {
char *line = NULL;
size_t linelen = 0;
Things *things = Things_new();
while (getline(&line, &linelen, input) > 0) {
handle_line(line, things);
}
return things;
}
这是重复劳动。
有没有办法让字符串数组伪装成FILE *
指针?或相反亦然?或者是否有更好的模式来处理这个问题?
奖励积分:解决方案应该使 char *
或 char **
可用于标准文件函数,如 fgets
和 获取线路
。
最佳答案
您可以使用包含 FILE*
的可区分 union 和一个指向数组的指针,然后写一个get_next
用它做正确事情的函数。
typedef struct {
enum { is_file, is_array } type;
union {
FILE *file;
struct {
int index;
int size;
char **lines;
} array;
} data;
} file_or_array;
char *get_next(file_or_array foa) {
if (foa.type == is_file) {
char *line = NULL;
size_t linelen = 0;
getline(&line, &linelen, foa.data.file);
return line;
} else {
if (foa.data.array.index < foa.data.array.size) {
return strdup(foa.data.array.lines[foa.data.array.index++]);
} else {
return NULL;
}
}
}
调用strdup()
是使这项工作始终如一的必要条件。自 getline()
返回一个新分配的字符串,调用者需要释放它,当从数组中返回一个字符串时,它也会做同样的事情。然后调用者可以在这两种情况下安全地释放它。
关于char * 或 char ** 可以伪装成 FILE * 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34887996/