热将 TXT 文件转换为结构数组 - 分段错误?

Hot to convert TXT File to Array of struct - segmentation fault?

正在尝试从文本文件中提取数据并将该数据放入数组中。

文件包含一定数量的行,每一行都遵循相同的配置:

Number FamilyName FirstName GPA

需要的数组是struct数组

#include<stdio.h>
#include<stdlib.h> 
#include<string.h>
#define MAX 25

typedef struct ppl {
    int login;
    char *p_name;
    char *p_surname;
}person;

int main(void)
{
    char *line = NULL;
    person *data=malloc(MAX*sizeof(person)); 
    float *gpa=malloc(MAX*sizeof(float)); 
    size_t length=0;

    FILE* txtfile;

    if ((txtfile=fopen("file.txt","r"))==NULL) return -1;

    int i=0;               // the counter for the for loop
    int buf_ID;            // buffer variable for the sscanf test
    char buf_name[256];    // same
    char buf_surname[256]; // same
    float buf_grade;       // same

    while ((read = getline(&line, &length,txtfile)) != -1 && i<MAX) 
    {
        if(sscanf(line,"%d %s %s%*s %f", &buf_ID, buf_name, buf_surname, &buf_grade)==4)
        {  
             data[i].login=buf_ID;
             data[i].p_name= malloc(strlen(buf_name)+1);
             strcpy(data[i].p_name, buf_name);
             data[i].p_surname= malloc(strlen(buf_surname)+1);
             strcpy(data[i].p_surname, buf_surname);
             gpa[i]=buf_grade;

             i++;
         }
     }                        

    int j;

    printf("ID | Name | Surname | GPA\n");

    for(j=0;j<i;j++)
    {
        printf("%d | %s | %s | %f\n", data[j].login, data[j].p_name, data[j].p_surname, gpa[j]);
    }
    fclose(txtfile);
    return 0;
}

(经常编辑的代码 - 我正在填充无用的文本,因为 post 不会以其他方式发布)

我看到你现在为你的数组分配了内存。好

现在关于 char * 缓冲区 buf_name 等。也许最好在这里进行静态分配,例如

char buf_name[256];

您将重新使用此缓冲区,因此静态分配没问题。


下一步:

查找 getline 函数:http://man7.org/linux/man-pages/man3/getline.3.html 并检查所有参数是否正确。


现在使用调试器将程序步进 sscanf。跨过它并检查变量是否已被 sscanf 正确读取(使用调试器是学习 C 的重要部分)。

接下来要问问自己,您的人员数组是否具有所需的全部内存。如果不是,你打算如何分配内存?


您已经使用 malloc 分配了一组人员。每个人都有一些与之相关的数据。数据由原始类型复合类型组成。基本类型是 int、float、double 和 char。复合类型由其中的一些组成。字符串是复合类型,因为它由多个字符组成。

所以你在数组中的人有与他们相关的字符串数据,作为指针,但指针没有与之相关的内存。您需要分配内存来保存字符串数据。你的数据->p_name=malloc(MAX*100);`不正确。

对于你阅读的每个人,你应该分配字符串内存来保存 sscanf 放入固定大小缓冲区的字符串数据:

data[i].p_name= malloc(strlen(buf_name)+1);
strcpy(data[i].p_name, buf_name);

其他字符串数据也一样。 (当然,你在循环中执行此操作!)

Nb:对于原始类型,数据由编译器分配;对于复合类型,您必须分配内存。

Nb: C 中的字符串以空字符结尾。因此所需的内存比字符串的长度多一倍。

What is that second sscanf doing there in your loop???

最后复制ID:

data[i].login= buf_id;

请注意,您没有将成绩存储在 person 中,并且 gpa 没有分配内存(因此您可能会再次遇到段错误)。


您的程序现在 运行 不会出现段错误。但是你的循环不正确:

你有一个 for 循环正好循环了 25 次;在循环中,你有一个 while 循环,它读取数据并将其放入 persons 中。但是 persons 的索引只在 for 循环中更新,而不是在 while 循环中更新。读取最后一行数据后,while 循环停止,for 循环的下一次迭代开始。但是,没有更多的数据。

所以你需要另一种类型的循环,循环 最多 25 次(因为你没有更多的人)并且没有更多数据时停止。

一个for循环就可以了; while 循环也可以。但不是两者。你能想出这两种变体吗?


您的程序现在 运行。最后一点:"clean up!" 删除不再需要的东西,确保代码正确缩进和格式化,并添加一个循环来打印数组,这样你就可以检查并正确查看它 运行。

希望您在开发这个程序时玩得开心。