char * 或 char ** 可以伪装成 FILE * 吗?

标签 c file file-io io

在 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/

相关文章:

c - INT 13 扩展读入 C

c - 如何左移大于 64 位的值?警告 : shift count >= width of type [-Wshift-count-overflow]

c - 为什么 fread() 给出看似随机的数据?

ruby - 更快的 CSV + 试图找到独特的项目

python - 如何在我的程序中更好地使用日志记录模块?

c++ - 静态链接 C++ 和 C 库时的 undefined reference

java - 如何在执行代码时刷新 src/main/resources 文件夹?

用于输入文件按钮的 Javascript,以通知文件上传完成

C文件读取留下乱码

C fgets 和 sscanf 循环 : prevent useless looping