c - 将 .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 中的每个条目都需要被释放,直到您到达 terminating NULL
。分配同时分配了子指针、结构和结构内容,因此每个城市只有一次free
调用。
特别的兴趣点:缓冲区被提前解析成块。然后立即分配城市结构,因为我们可以查看结构元素并说出我们需要多少空间。如果在读入后不编辑记录本身,则这样做是惯用的,因为代码既短又快。我很生气试图弄清楚如何处理错误,只是说 readerrno
确实有效,但有些人不喜欢 clears 的代码errno
。在幸福的道路上,清理errno
很好。只有在错误路径上才会导致问题。
我还没有运行此代码。它可能有错误。
推荐阅读
- postgresql - Postgresql向函数内的交叉表查询添加参数
- sql - 使用自动生成的 ID 将表中的数据插入到另一个表中
- javascript - 如何修改 Node.js Readline 中的光标线?
- javascript - 是否可以使用相同的函数来设置不同对象的状态
- r - 如何将每日日期转换为每月或每月的第一天
- python-3.x - 移动安全框架 (MobSF) 安装问题
- python - python:将'dd/mm/yyyy'中的日期粘贴到excel将其转换为'mm/dd/yyyy'
- java - 当返回值为枚举类型时,函数确实返回 null
- python - 如何继续将文本块写入python中的文件
- python - Python pandas - 使用 pd.groupby().agg() 获得第二高值的数据框