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

Sch*_*ern 6 c io file-io file

在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;
}
Run Code Online (Sandbox Code Playgroud)

这是一种重复的努力.

有没有办法让一个字符串数组伪装成FILE *指针?或相反亦然?或者是否有更好的模式来处理这个问题?

对于奖励积分:解决方案应该与标准文件函数一样char *char **可用,如fgetsgetline.

Bar*_*mar 6

你可以使用一个包含a FILE*和一个指向数组的指针的区别联合,然后编写一个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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫strdup()是必要的,以使这项工作始终如一.由于getline()返回一个新分配的字符串,调用者需要释放该字符串,因此从数组返回字符串时也会执行相同的操作.然后呼叫者可以在两种情况下安全地释放它.


Ste*_*mit 5

有一个非标准的功能fmemopen,可以打开char []进行读写.我认为它可以在大多数GNU libc版本和大多数Linux版本中使用.

(这使您可以读取或写入单个字符串,而不是您询问的字符串数组.)