【问题标题】:Segmentation Fault in a function based on a linked list基于链表的函数中的分段错误
【发布时间】:2020-03-17 21:07:54
【问题描述】:

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

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

【问题讨论】:

  • 您不应使用下划线作为struct 标签的第一个字符。
  • @JL2210 我的导师制作了结构,该函数是我被允许操作的唯一代码
  • 好吧,把它传给你的导师。以下划线开头的 IIRC 标识符保留给实现。
  • “老师,我试图让 StackOverflow 完成我的作业,他们说……”
  • @JL2210 -- 这不正是教师使用的惯例 -- 不要更改以 _ 开头的内容吗?对我来说似乎是正确的

标签: c linked-list


【解决方案1】:

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

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

【讨论】:

  • 感谢您提醒我们退后一步,从更广泛的角度看待事物 - 即从研究指针的学生的角度来看。
  • @MaximSagaydachny 我是否在 else 块中造成损坏?
猜你喜欢
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
相关资源
最近更新 更多