c-Hot将TXT文件转换为结构的数组-分段错误



尝试从文本文件中提取数据并将这些数据放入数组中。

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

Number FamilyName FirstName GPA

所需的数组是结构的数组。

#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 | GPAn");
for(j=0;j<i;j++)
{
printf("%d | %s | %s | %fn", data[j].login, data[j].p_name, data[j].p_surname, gpa[j]);
}
fclose(txtfile);
return 0;
}

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

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

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

char buf_name[256];

您将重用这个缓冲区,所以静态分配是可以的。


下一步:

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


现在使用调试器并将程序逐步转到sscanf。跨过它,检查sscanf是否正确读取了变量(使用调试器是学习C的重要组成部分)。

下一件事是问问自己,你的一系列人是否拥有所需的所有记忆。如果没有,你将如何分配内存?


您已经使用malloc分配了一组人员。每个人都有一些相关的数据。这些数据由基元类型

复合类型因此,数组中的人员具有与他们相关联的字符串数据,作为指针,但指针没有与他们相关的内存。您需要分配内存来保存字符串数据。您的数据->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中的字符串以空字符结尾。因此,所需的内存比字符串的长度多一个。

循环中的第二个sscanf在做什么

最后,复制ID:

data[i].login= buf_id;

请注意,您没有将分数存储在人员中,并且gpa没有分配内存(因此您可以再次获得seg错误)


您的程序现在将在没有seg故障的情况下运行。但你的循环不正确:

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

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

for循环可以很好;while循环也可以。但不是两者都有。你能想出这两种变体吗?


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

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

最新更新