我有两个结构,我有一个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.dat\n");
}
fscanf(fp,"%d",&NumOfStudents);
printf("%d\n",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);
}
}
答案 0 :(得分:3)
(*students[NumOfStudents]).firstName=(char)malloc(sizeof(char[30]));
首先,演员阵容是完全错误的。施放到char
会丢失信息
其次,在C中不要从malloc()
转换返回值。它充其量是多余的,并且可能隐藏编译器在没有强制转换的情况下捕获的错误。
无论如何你要投,转向char*
。
答案 1 :(得分:2)
使用students
指针时,您似乎有一个额外级别的指针,您不需要引起混淆。您还可以访问已分配的数组末尾。
所以而不是
StudentType *students[30];
这给你一个30个指向StudentType的数组,我想你可能只是想要:
StudentType *students;
这只是一个指向StudentType的普通指针,可以用作动态分配数组的基础。然后当你进行分配时,你会这样做:
students = malloc(sizeof(*students) * NumOfStudents);
在使用之前,您必须初始化每个StudentTypes。
for(i=0;i<NumOfStudents;i++)
{
students[i].firstname = malloc(30);
students[i].lastname = malloc(30);
}
请注意,现在每个StudentType都作为学生数组中的元素student[i]
直接访问,而不是您错误的*students[i]
。您可以将其扩展到其余代码。请记住,您只能从索引0访问NumOfStudents-1,因此请勿使用学生[NumOfStudents]。
您将遇到的另一个问题是,当您使用fscanf()时,您需要传递变量的地址以使用&符号运算符存储结果。目前,您只传递了该值,例如您应该使用&students[i].marks.firstAssignment
而不是(*students[i]).marks.firstAssignment
,假设您还修复了指针错误。
答案 2 :(得分:1)
这两个陈述是错误的:
(*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)
。
答案 3 :(得分:0)
(*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”的全局索引可被视为不良风格。