将数据从文件保存到c中的结构

Posted

技术标签:

【中文标题】将数据从文件保存到c中的结构【英文标题】:Saving data from a file to a struct in c 【发布时间】:2021-11-20 23:15:23 【问题描述】:

我有两个必须用学生数据填充的结构。数据格式为:

年龄、姓名、年级、年龄、组别、轮次

文件头中是数据中的学生人数。

struct school //school

    char group; //A,B,C,D,E,F
    char turn; //Morning, AFTERNOON
;

struct student

    char *name; 
    char *grade;
    int age;
    struct school *E;
student[6];

我尝试先从只有年龄、姓名和年级的文本中保存数据,看看我是否可以做到:

void get_file(const char* file, int *n) //n is the amount of students
    FILE* fptr;

    fptr = fopen(file, "r");
    if (fptr == NULL)
        printf( "\n Error \n");
        exit(1);
    
    char* temp;
    int tam = 0;
    fscanf(fptr, "%d", n); //size of the list of students 
    for(int i= 0; i < *n; i++)

        fscanf(fptr, "%d,%s,%s", &student.age[i],temp, student[i].grade);
        tam = strlen(temp);
        student[i].name = (char*)malloc(tam * sizeof(char));
        strcpy(student[i].name, temp);
        printf("%s\n", student[i].name);//to see if it's correct the content
     
    fclose(fptr);

但是,student.name 存储例如 "Josh, A+",而它应该只是 "Josh"。我该如何解决这个问题?

这是一个任务。

编辑: 我的数据是这样的

4 //size of list
Josh,A,20,D,M
Amber,B,23,E,M
Kevin,C,22,D,A
Adam,A+,21,C,A

使用 Remy Lebeau 的解决方案,我得到了这个

void get_file(const char* file, int *n)
    *n = 0;

    FILE* fptr = fopen(file, "r");
    if (fptr == NULL)
        printf( "\n Error \n");
        exit(1);
    

    char name[80];
    char grade[2];

    fscanf(fptr, "%d", n); //size of the list of students 

    for(int i = 0; i < *n; i++)
        fscanf(fptr, "%80[^,],%2[^,],%d,%c,%c", &student[i].age, name, grade,&student[i].group, &student[i].turn);
        student[i].name = strdup(name);
        student[i].grade = strdup(grade);
     

    fclose(fptr);

但是我遇到了问题,因为我做了这个改变

struct student

    char *name; 
    char *grade;
    int age;
    struct school E; //it was struct school *E
student[6];

要传递信息,但是老师说我不能改,那我怎么加载struct school *E的信息呢?

【问题讨论】:

发布答案后,请不要通过应用答案中建议的更正来更改您的问题,因为这会使答案无效。 将数据从文件移动到内存中通常称为加载,而不是保存。 【参考方案1】:

您致电fscanf() 存在多个问题:

&amp;student.age[i] 必须是 &amp;student[i].age

tempstudent::grade 是未初始化的指针,它们不指向任何地方,因此将数据读取到它们指向的内存是未定义的行为fscanf() 不会为你分配内存,你需要自己为fscanf() 预先分配char[] 缓冲区,然后才能读入。

%s 读取非空白字符包括 ',',这就是为什么您的代码不会在Josh 之后的, 上停止。尝试在该字段中使用 %[^,] 而不是 %s

试试这样的:

void get_file(const char* file, int *n)
    *n = 0;

    FILE* fptr = fopen(file, "r");
    if (fptr == NULL)
        printf( "\n Error \n");
        exit(1);
    

    char name[256];
    char grade[5];

    fscanf(fptr, "%d", n); //size of the list of students 

    for(int i = 0; i < *n; i++)
        fscanf(fptr, "%d,%255[^,],%4s", &student[i].age, name, grade);
        student[i].name = strdup(name);
        student[i].grade = strdup(grade);
        printf("%d %s %s\n", student[i].age, student[i].name, student[i].grade);
     

    fclose(fptr);

更新

您现在显示的文件数据与您描述的格式不匹配,这是您的代码所期望的。您将文件数据描述(并编码)为:

age, name, grade, age, group, turn(为什么是 2 个年龄?)

但你显示的更像:

name, grade, age, group, turn

您将fscanf() 中的格式字符串更改为这种新格式,但您没有更改读取变量的顺序以匹配此格式。因此,您将name 值读入age 字段,将grade 值读入name 字段,并将age 值读入grade 字段。

此外,您甚至没有尝试正确处理 groupturn。它们位于完全不同的结构中,您没有为其分配任何内存。您需要分配一个school 对象,将groupturn 读入其中,然后将其分配给student[i].E

话虽如此,请尝试更多类似的东西:

struct school

    char group; //A,B,C,D,E,F
    char turn; //Morning, AFTERNOON
 school[6];

struct student

    char *name; 
    char *grade;
    int age;
    struct school *E;
student[6];

void get_file(const char* file, int *n)
    *n = 0;

    FILE* fptr = fopen(file, "r");
    if (fptr == NULL)
        printf( "\n Error \n");
        exit(1);
    

    char name[81];
    char grade[3];

    fscanf(fptr, "%d", n); //size of the list of students 

    for(int i = 0; i < *n; i++)
        student[i].E = &school[i]; // or, use malloc() instead, if needed...
        fscanf(fptr, " %80[^,],%2[^,],%d,%c,%c", name, grade, &(student[i].age), &(student[i].E->group), &(student[i].E->turn));
        student[i].name = strdup(name);
        student[i].grade = strdup(grade);
     

    fclose(fptr);

【讨论】:

我试过了,它只打印列表中的第一个名字 一个问题是您的代码没有尝试读取文件中的所有数据。只读取了第一个学生的一部分数据后,留下了更多数据。因此,当您的循环尝试读取第二个学生时,它实际上是从第一个学生那里读取剩余的数据。如果你不打算读取一个学生的所有数据,我建议你使用getline()或类似的函数一次读取整个学生,然后你可以使用sscanf()解析出你需要的值。 我对@9​​87654354@ 做了同样的事情:我创建了另一个变量,比如temp 来存储 好点,我错过了。我已经更新了我的答案以说明这一点。无论如何,当您没有显示文件数据的实际外观时,很难诊断您的问题。不要描述数据,显示数据。 我想将所有数据存储在文件中,我制作的函数是一种有效的方法吗?我没有其他想法将信息存储在指针```名称```

以上是关于将数据从文件保存到c中的结构的主要内容,如果未能解决你的问题,请参考以下文章

C ++将结构中的字符串保存到文本文件中

c语言中如何修改储存在文件的结构体内容中。小文件

如何将数据结构中的字段保存到 Matlab 中的文件名字段?

如何将 SQLite 文件从 Documents 目录保存回目标 C 中的主包?

将数据从文件加载到c中的数组

c语言读取文件然后保存到数组中