c - 基于链表的函数中的分段错误
问题描述
编写一个函数以将成绩添加到链表的末尾。有一个学生链表,每个学生都包含一个指向成绩链表的指针——
typedef struct _grade {
char name[10];
double value;
struct _grade *next;
} Grade;
////////////////////////////////////////////////////////////////////////////////////////
typedef struct _student {
char *lastName;
char *firstName;
Grade *headGradeList;
struct _student *next;
} Student;
编译后运行代码时,出现分段错误。我很确定它出现在我的带有 strcmp 的 if 语句中。有什么建议么?
// add a grade to the specified student
// 1. Make sure a student by that name exists (so you can add grade to it)
// 2. If the specifed grade already exists, update the grade's value to the new value
// 3. Otherwise, add the grade to the end of the student's grade list (add-at-end)
void addGrade(Student *headStudentList, char last[], char first[], char gradeName[], double value) {
int flag=0;
Student *dummy=headStudentList;
Grade *temp=malloc(sizeof(Grade));
strcpy(temp->name,gradeName);
temp->value=value;
temp->next=NULL;
while(dummy!=NULL){
printf("Here 1");
if(strcmp(dummy->lastName, last)==0 && strcmp(dummy->firstName, first)==0){
flag=1;
if(dummy->headGradeList==NULL){
strcpy(dummy->headGradeList->name, gradeName);
dummy->headGradeList->value=value;
dummy->headGradeList->next=NULL;
}
else{
while(1){
if(dummy->headGradeList->next==NULL){
dummy->headGradeList->next=temp;
break;
}
dummy->headGradeList=dummy->headGradeList->next;
}
}}
dummy=dummy->next;
}
if(flag==0){
printf("ERROR: student does not exist\n");
}
}
解决方案
您忘记使用新创建的条目初始化成绩列表
if(dummy->headGradeList==NULL){
strcpy(dummy->headGradeList->name, gradeName);
dummy->headGradeList->value=value;
dummy->headGradeList->next=NULL;
}
它应该是:
if(dummy->headGradeList==NULL){
dummy->headGradeList=temp;
}
dummy->headGradeList 在您的情况下指向 0(NULL)地址。
dummy->headGradeList->name 也计算为 0 - 代码期望您的成绩记录在 0 处找到,并且 name 字段也在那里,因为它从结构的开头就已经为 0。
因此,您的代码实际上将 0 作为地址传递给 strcpy 函数,该函数试图将数据复制到位于地址 0 的缓冲区中。
在大多数情况下,那里什么都没有,而且这个虚拟内存没有映射到任何物理内存。
所以这就是崩溃的原因。
此外,代码中还有 3 个错误:
1)else块应该属于成绩列表检查(不是学生姓名)
2)检查现有成绩(很可能您需要覆盖之前添加到列表中的成绩的值)
3)您正在破坏(通过它时重置成绩列表)。您需要使用单独的新变量,该变量将用作指向列表中当前成绩的指针。您正在使用指向头部的指针在列表中导航(即,您正在修改头部,而它应该是不可变的,除非您决定插入等级而不是将其添加到尾部)
Grade *current = dummy->headGradeList; // point iterator variable to head
//go to tail
while (current->next){
// here you need to check grade name and chenge existing grade.
current = current->next;
}
current->next=temp; // add new grade to the tail
或者,您可以将成绩插入头部(如果您不关心成绩的顺序和重复)
if(we found right student){
// it does not matter whether previous head pointed to NULL or good chain. just chain it back.
temp->next=dummy->headGradeList;
dummy->headGradeList=temp;
}