在C语言中将一组结构体写入二进制文件

6
我可以帮您进行翻译,以下是翻译的结果:

我有一个结构体数组,想将其写入二进制文件。我有一个write.c程序和一个read.c程序。写入程序write.c似乎正常工作,但当我运行read.c程序时,出现了分段错误。由于我刚开始学习C语言,所以希望有人能够查看我的代码,找出明显的错误。我保证代码不会太长 :)

write.c:

#include <stdlib.h>
#include <stdio.h>

struct Person 
{
    char f_name[256];
    char l_name[256];
    int age;
};

int main(int argc, char* argv[])
{
    struct Person* people;
    int people_count;

    printf("How many people would you like to create: ");
    scanf("%i", &people_count);
    people = malloc(sizeof(struct Person) * people_count);  

    int n;
    for (n = 0; n < people_count; n++)
    {
        printf("Person %i's First Name: ", n);
        scanf("%s", people[n].f_name);

        printf("Person %i's Last Name: ", n);
        scanf("%s", people[n].l_name);

        printf("Person %i's Age: ", n);
        scanf("%i", &people[n].age);
    }

    FILE* data;
    if ( (data = fopen("data.bin", "wb")) == NULL )
    {
        printf("Error opening file\n");
        return 1;   
    }

    fwrite(people, sizeof(struct Person) * people_count, 1, data);
    fclose(data);

    return 0;
}

read.c:

#include <stdlib.h>
#include <stdio.h>

struct Person 
{
    char f_name[256];
    char l_name[256];
    int age;
};

int main(int argc, char* argv[])
{
    FILE* data;
    if ((data = fopen("data.bin", "rb")) == NULL)
    {
        printf("Error opening file\n");
        return 1;
    }

    struct Person* people;

    fread(people, sizeof(struct Person) * 1/* Just read one person */, 1, data);
    printf("%s\n", people[0].f_name);

    fclose(data);

    return 0;
}

感谢您的帮助!

这个问题每天被问了多少次?应该有一个“C”常见问题解答,让我们可以指向答案,而不是一遍又一遍地写下来。 - KevinDTimm
4个回答

6
struct Person* people;

这只分配了一个指向结构体的指针,但是你没有为实际的结构体内容分配任何空间。要么像写程序一样使用malloc,要么尝试类似于下面的方法:

struct Person people;
fread(&people, sizeof(people), 1, data);

4

首先需要为人员分配内存。将struct Person* people;修改为struct Person* people = malloc(sizeof(struct Person));。最后别忘了在结束时释放内存:free(people);


你能解释一下在malloc(sizeof(struct Person))之前的(struct Person*)是什么意思吗?那是一个强制类型转换吗? - John Jacquay
@jjacquay712 是的,没错。我只是不太喜欢过多依赖默认编译器选项。 - Przemek Kryger
1
不要malloc的结果进行强制类型转换。这是标准和明确定义的C行为,也是惯用的C风格。您可以保证获得隐式转换。如果您进行了强制类型转换,则编译器将无法诊断错误,如果您忘记了#include <stdlib.h> - Karl Knechtel
@Karl Knechtel 谢谢您指出这个问题。已编辑并删除了强制转换。 - Przemek Kryger

2

在执行fread之前,您需要将内存分配到指针变量people中,或者(更简单的方法)直接读取到本地变量中:

struct Person people;

fread(&people, sizeof(struct Person) * 1/* Just read one person */, 1, data);

2

您需要为要读取的数据分配空间:

people = malloc(sizeof(*people)*numPeople);

一旦OP决定读取一个以上的元素,这似乎更具扩展性。可以改为在单个本地变量上循环。 - Steve Townsend

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接