将.dat数据添加到C结构



所以我必须快速使用C语言,并且需要这样的指导,因为我通常不使用C语言。

我有City.dat文件,里面有一些数据(我简化了它的StackOverflow(:

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调用。

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

我尚未运行此代码。它可能有错误。

最新更新