将 .dat 数据添加到 C 结构?

Adding .dat data to a C struct?

所以我必须快速了解 C 并需要指导,因为我通常不使用 C。

我有 City.dat 个文件,其中包含一些数据(我在 Whosebug 中对其进行了简化):

Postal-Code | City 
32            San Diego

在我的 City.h 文件中,我为其创建了结构:

typedef struct{

    int postalCode;
    char cityName;
} City;


typedef struct {
    City **city;
} CityList;

我应该如何处理 City.c 中的迭代以从 city.dat 收集所有数据?显然,我需要一个 for 循环,但我想看一个示例如何从 dat 文件中读取数据并打印出收集的城市?

char cityName;

真的应该

char *cityName;

我们实际上可以在这里使用一个灵活的数组,但我们不会,因为您的真实结构可能有多个字符串。

收集循环很简单。

#define SPLIT 15

// Stupid helper function to read a single line no matter how long.
// Really should be in the standard library but isn't.
static int readline(FILE *h, char **buf, size_t *nbuf)
{
    if (!*buf) {
        *buf = malloc(128);
        nbuf = 128;
    }
    size_t offset = 0;
    do {
        if (offset + 1 >= *nbuf) {
            // Just keep growing the line buffer until we have enough room.
            size_t nbuf2 = *nbuf << 1;
            char *buf2 = realloc(*buf, nbuf2);
            if (!buf2) return -1;
            *buf = buf2;
            *nbuf = nbuf2;
        }
        if (!fgets(buf + offset, *nbuf - offset, h)) return -1;
        offset += strlen(buf + offset);
    } while (offset > 0 && buf[offset - 1] == '\n');
    return 0;
}

CityList readfile(const char *file);
{
    errno = 0; // Check errno for short read.
    FILE *f = fopen(file);
    if (!f) return NULL;
    char *buf = NULL;
    size_t nbuf = 0;
    City **cities = NULL;
    size_t ncities;
    size_t acities;
    if (readline(f, &buf, &nbuf)) return NULL; // get rid of header line
    acities = 4;
    ncities = 0;
    cities = malloc(acities * sizeof(City**));
    if (!cities) return NULL;
    cities[0] = NULL; // Mark list empty
    while (!readline(f, &buf, &nbuf)) {
        // get new city struct
        int n = strtol(buf);
        int len = strlen(buf);
        if (len > 0 && buf[len] == '\n') buf[len--] = 0; // Cut off trailing \n
        if (len + 1 > SPLIT) /* validity check */ {
            if (ncities + 1 == acities) {
                size_t ncities2 = ncities << 1;
                City **cities2 = realloc(ncities 2 * sizeof (City**));
                if (!cities2) break;
            }
            // Allocate the entire struct and its data all at once.
            char *citybuf = malloc(sizeof(City*) + sizeof(City) + len - SPLIT + 1);
            City **city = (City*)citybuf;
            // Slot all the stuff into the structure
            city[0] = citybuf + sizeof(City *);
            city[0]->postalCode = n; // Value saved from above.
            city[0]->cityName = citybuf + sizeof(City *) + sizeof(City);
            strcpy(city[0]->cityName, buf + SPLIT);
            // Add city to list
            cities[ncities] = city;
            cities[++ncities] = NULL; // Mark end of list
        }
    }
    free(buf);
    fclose(f);
    CityList l = { cities };
    return l
}

当你来免费的时候; CityList 中的每个条目都需要被释放,直到您到达终止 NULL。分配一次分配了子指针、结构和结构内容,因此每个城市只有一个 free 调用。

特殊兴趣点:缓冲区被提前解析为块。然后一次分配城市结构,因为我们可以查看结构元素并说出我们需要多少space。如果记录本身在读入后没有被编辑,那么这样做是惯用的,因为代码既短又快。我很生气试图弄清楚如何处理错误,只是说读 errno 确实有效,但有些人不喜欢清除 errno 的代码。在快乐的道路上,清除 errno 就可以了。只有在错误路径上才会导致问题。

我没有运行这个代码。它可能有错误。