使用fscanf将数据输入动态结构指针数组?

使用fscanf将数据输入动态结构指针数组?,c,segmentation-fault,dynamic-arrays,scanf,C,Segmentation Fault,Dynamic Arrays,Scanf,我有一项任务,遇到了一些困难。下面的代码应该从文件中获取输入,将其读入我定义的结构中,并且这样做不限制输入行的数量。但是,它在24号线发现了以下故障: 这似乎解决了这个问题。我将运行一些测试以确保。在第19行,您为N个学生指针分配了足够的空间,但没有为学生自身结构分配空间。您需要执行以下操作: for( int i = 0; i < N; i++) { S[i] = malloc(sizeof(struct __student)); } while (fscanf(fp, "%

我有一项任务,遇到了一些困难。下面的代码应该从文件中获取输入,将其读入我定义的结构中,并且这样做不限制输入行的数量。但是,它在24号线发现了以下故障:


这似乎解决了这个问题。我将运行一些测试以确保。

在第19行,您为N个学生指针分配了足够的空间,但没有为学生自身结构分配空间。您需要执行以下操作:

for( int i = 0; i < N; i++) {
     S[i] = malloc(sizeof(struct __student));
}
while (fscanf(fp, "%d %32[^,],%32s%f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade) == 4) {
for(int i=0;i
除了malloc问题之外,这两行代码也存在重大问题

while(!feof(fp)){
    fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade ); // segfault occurs on this line
一个问题是,您的
lname
fname
字段是固定大小的33个字符数组,这意味着如果您的输入在该点超过32个字符,您将运行数组的末尾并损坏内容。另一个问题是,您没有检查
fscanf
的返回值以查看是否出现了错误(例如EOF),这导致您在到达文件末尾时尝试打印垃圾记录。相反,您想要的是:

for( int i = 0; i < N; i++) {
     S[i] = malloc(sizeof(struct __student));
}
while (fscanf(fp, "%d %32[^,],%32s%f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade) == 4) {
用于循环控制

编辑


while(!feof(fp))
(以及为什么它几乎总是一个错误)的问题是
feof(fp)
只有在您尝试读取文件末尾之后才会返回true。读取最后一行后,
feof(fp)
仍然返回false,因此再次进入循环并尝试读取另一行。该读取失败,但由于您没有检查
fscanf
的返回值,因此您没有意识到它,而是在数组中获得了一个额外的垃圾值。

这看起来像一个奇怪的链接列表\2D数组。你想要哪个?你能解释一下输入行的格式吗<代码>%d%[^,],%s%f“你为什么要用
,”
?安德烈,这是疏忽,我道歉。早些时候我尝试了一种新的方法,但发现它不是我所需要的@AdriánLópez输入数据的格式为。我只是使用扫描集来去除逗号。我很抱歉没有提到那件事!是的,您必须为每个学生分配内存,或者您可以首先分配一个
学生数组,而不是一个指向学生的指针数组。例如,用
S=(学生*)malloc(学生*)*N)替换
S=(学生*)malloc(学生*)*N)
。实际上,问题在于内存分配。你需要内存来存储
N*结构的大小,而不是
N*指向你的结构的指针的大小。哦,糟糕,看起来你用编辑回答了自己的问题。我回答了,但我会接受任何一种方式的答案,因为它是正确的。谢谢,谢谢你的回答。我不检查输入大小的原因是,正如我所说的,这是一个赋值,并且输入大小保证是一致的。当然,如果不是这样的话,我会检查一下的。感谢您提到返回值,不过,我确实应该养成一种习惯,在可能的情况下使用它进行错误检测。有一件事:while(!feof(fp))和while(fscanf(…)==4)之间的区别是什么?因为我是从一个一致的输入中读取数据的,所以不能匹配这些项目基本上等同于它是EOF,不是吗?非常感谢。