【问题标题】:Adding .dat data to a C struct? [closed]将 .dat 数据添加到 C 结构? [关闭]
【发布时间】:2020-11-22 16:57:04
【问题描述】:

所以我必须在 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 文件中读取数据并打印出收集到的城市?

【问题讨论】:

  • 你的问题太宽泛了。如果您不知道如何从 C 中读取文件,则应从教程开始:tutorialspoint.com/ansi_c/c_working_with_files.htm 如果此文件有特定内容给您带来麻烦,则应指定它。如果您希望此站点上的某个人为您编写整个作业代码,那么您就在错误的站点上。祝你好运!
  • @LevM.:我决定不把它当作家庭作业。虽然我真的不知道,但他说问题已经减少,因此他将无法复制/粘贴任何答案。然后我给出了完整流利的答案。如果这在家庭作业中被丢弃,它会像大拇指一样突出。

标签: c file-io


【解决方案1】:
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 很好。只有在错误路径上才会导致问题。

我还没有运行此代码。它可能有错误。

【讨论】:

  • 正是我想要的入门指南。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多