首页 > 解决方案 > 基于链表的函数中的分段错误

问题描述

编写一个函数以将成绩添加到链表的末尾。有一个学生链表,每个学生都包含一个指向成绩链表的指针——

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");
    }
}

标签: clinked-list

解决方案


您忘记使用新创建的条目初始化成绩列表

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;
}

推荐阅读