我有两个结构,我有一个30指针的StudentType数组。我对malloc()
有问题。当我编译它时,它是可以的。但当我尝试调试它时,在Dev c++中显示"Segmentation Fault"。
在Eclipse中,它在控制台上显示任何内容。我认为我的错误在于以下几行代码:
students[0]=(StudentType *)malloc(sizeof(StudentType)*NumOfStudents);
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
(*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));
这是我代码的一部分。
#include <stdio.h>
#include <stdlib.h>
typedef struct{
float firstAssignment;
float secondAssignment;
float midterm;
float final;
float finalMark;
}StudentRecordType;
typedef struct{
char *firstName;
char *lastName;
int idNumber;
StudentRecordType marks;
}StudentType;
StudentType *students[30];
char firstName[30];
char lastName[30];
int ReadFromFile();
int PrintAll();
int NumOfStudents;
int i;
int main(void)
{
ReadFromFile();
}
int ReadFromFile()
{
FILE *fp;
fp=fopen("project2-askhsh2.dat","r");
if(fp==NULL)
{
printf("Error opening file.n");
}
else
{
printf("Successful open of project2-askhsh2.datn");
}
fscanf(fp,"%d",&NumOfStudents);
printf("%dn",NumOfStudents);
students[0]=(StudentType *)malloc(sizeof(StudentType)*NumOfStudents);
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
(*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));
for(i=0;i<NumOfStudents;i++)
{
(*students[i]).idNumber=i;
fscanf(fp,"%s %s", (*students[i]).firstName,(*students[i]).lastName);
fscanf(fp,"%f %f %f %f",(*students[i]).marks.firstAssignment,(*students[i]).marks.secondAssignment,(*students[i]).marks.midterm,(*students[i]).marks.final);
printf("%s",(*students[i]).firstName);//, students[i].lastName);
}
}
(*students[NumOfStudents]).firstName=(char)malloc(sizeof(char[30]));
首先,演员阵容完全错误。投射到char
会丢失信息
其次,在C中,不要强制转换malloc()
的返回值。它充其量是多余的,并且可能会隐藏编译器在没有强制转换的情况下会捕捉到的错误。
如果要进行强制转换,请强制转换为char*
在使用students
指针时,您似乎有一个额外级别的指针,不需要引起一些混乱。您还可以访问已分配的数组的末尾。
所以不是
StudentType *students[30];
这给了你一个30个指向StudentType的指针数组,我想你可能只是想要:
StudentType *students;
它只是一个指向StudentType的普通指针,可以用作动态分配数组的基础。然后当你进行分配时,你会这样做:
students = malloc(sizeof(*students) * NumOfStudents);
在使用这些StudentType之前,您必须初始化它们中的每一个。
for(i=0;i<NumOfStudents;i++)
{
students[i].firstname = malloc(30);
students[i].lastname = malloc(30);
}
请注意,现在每个StudentType都作为一个元素从students数组中直接访问为student[i]
,而不是错误的*students[i]
。您可以将其扩展到代码的其余部分。请记住,您只能从索引0访问NumOfStudents-1,因此不要使用students[NumOfStudents]。
您将遇到的另一个问题是,当您使用fscanf()时,您需要传递变量的地址,以便使用"与"运算符将结果存储在中。目前您只传递值,例如,您应该使用&students[i].marks.firstAssignment
而不是(*students[i]).marks.firstAssignment
,假设您也修复了指针错误。
这两条语句是错误的:
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
(*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));
C数组是零索引的,因此您试图取消引用一个超过数组大小的数组。假设您想要设置students[]
的最后一个元素的名字和姓氏,那么您需要取消引用索引NumOfStudents - 1
。
您不需要将malloc()
的结果强制转换为char *
(假设您正在编写C应用程序)。
sizeof(char)
是1,所以您只需要编写malloc(30)
。
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
我想你的意思是:
students[some_index]->firstName = malloc(30);
some_index的值低于NumOfStudents。
所以你的循环变成:
for(i=0; i < NumOfStudents ; i++)
{
/* students[] is an array of pointers
** students[i] is a pointer
*/
students[ i ] = malloc(sizeof *students[ i ]);
students[ i ]->idNumber=i;
students[ i ]->firstName = malloc(30);
students[ i ]->lastName= malloc(30);
fscanf(fp,"%s %s"
, students[i]->firstName
, students[i]->lastName
);
fscanf(fp,"%f %f %f %f"
, &students[i]->marks.firstAssignment
, &students[i]->marks.secondAssignment
, &students[i]->marks.midterm
, &students[i]->marks.final
);
printf("%s",students[i]->firstName);//, students[i].lastName);
}
使用名为"i"的全局索引可能被认为是糟糕的风格。