使用函数将节点添加到链表

adding a node to a linked list using a function

我目前有一个链表,需要向其中添加用户从键盘输入的数据,所以我有两个结构:

struct CourseInfo {
    int courseID;
    char courseName[30];
};
typedef struct CourseInfo courseinfo;
struct StudentInfo {
    char StudentID[10];
    char FirstName[21];
    char LastName[26];
    int num_course;
    courseinfo array[10];
    struct StudentInfo *next;
};

所以我目前有一个包含 3 个节点的链表。然后我需要调用一个函数并添加一个节点。该节点需要插入正确的位置,即它之前的学生 ID 需要小于它,之后的学生 ID 需要更大,所以我当前的 ID 是 111111111、333333333 和 444444444,我正在尝试添加 222222222所以它会排在第二位所以我的函数看起来像:

studentinfo *addStudent(studentinfo *data) //returns type studentinfo* now
{
    studentinfo *add;
    add = malloc(sizeof(studentinfo));
    add->next = NULL; //Now its set to NULL to begin
    int knt;
    printf("%s", "Adding new student:\nStudent ID: ");
    scanf("%s", add->StudentID);
    printf("%s", "First Name: ");
    scanf("%s", add->FirstName);
    printf("%s", "Last Name: ");
    scanf("%s", add->LastName);
    printf("%s", "Number of courses: ");
    scanf("%d", &add->num_course);
    for(knt = 0; knt < add->num_course; knt++) {
        printf("%s", "Course ID: ");
        scanf("%d", &add->array[knt].courseID);
        printf("%s", "Course Name: ");
        scanf("%s", add->array[knt].courseName);
    }
    if(searchStudentID(data, add->StudentID)) {
        puts("immediately inside if");
        while(data != NULL) {
            puts("Immediately inside while");
            if(strcmp(add->StudentID, data->StudentID) < 0) {
                puts("inside if");
                add->next = data;
                data = add;
            }
            else {
                puts("inside first else");
                studentinfo *PrevPtr = data;
                studentinfo *NPtr = data->next;
                while(NPtr != NULL) {
                    ("inside while(NPTR != NULL)");
                    if(strcmp(add->StudentID, NPtr->StudentID) < 0) {
                        add->next = PrevPtr;
                        PrevPtr->next = add;
                        break;
                    }
                    else {
                        puts("inside a differnet else");
                        PrevPtr = NPtr;
                        NPtr = NPtr->next;
                    }
                }
                if(PrevPtr->next == NULL) {
                    puts("inside last if");
                    add->next = NULL;
                    PrevPtr->next = add;
                }
            }
        }
    }
    else {
        puts("Found id");
    }
    return data; //returns data back to call
}

所以我添加了所有这些 puts 语句,因为我想看看为什么程序一直崩溃。所以puts语句puts("Inside a different else")陷入死循环,一直打印。函数 searchStudentID 只是 returns 1 如果我们还没有 ID,如果我们已经有它则为 0。我知道此功能有效,因此无需 post 它。

我觉得问题可能出在破解上;语句,因为它不会从第一个 while 循环中退出,而只会从内部循环中退出,但我不会 positive.The 调用此函数,看起来像:

list = addStudent(list); //Now the new data is stored in list

其中list是3个节点的链表

由于此函数更新列表,您需要它

studentinfo *addStudent(studentifo *data)

和 return 更新后的水头值。或者

void addStudent(studentifo **data)

并做

*data = <new thing>

我看到的问题:

  1. 您没有将 add->next 设置为 NULL

  2. 您正在本地更改 data

            add->next = data;
            data = add;
    

    在函数中局部更改 data 的值。它不会更改调用函数中的值。

  3. 你有支票

    while(data != NULL)
    

    if 声明之后

    if(searchStudentID(data, add->StudentID)) {
    

    但在 searchStudentID(data, add->StudentID) returns falsedata == NULL 开始时,我没有看到任何添加新学生的代码。

链表管理是管理节点指针,而不仅仅是节点。你想做几件事来让你自己更轻松:

  • 将输入步骤与搜索+插入步骤分开。无论它们看起来如何,它们都不属于一起。这给你带来的最大好处是将你的列表插入代码减少到它应该做的事情(只有它应该做的事情):管理链表。我一直保持你的完好无损,但你真的应该检查错误并在其他地方读取数据。

  • 使用指向指针的指针遍历列表。这样做的最大好处是消除了特殊情况下头部位置插入的需要。如果这是一个新节点最终会占据的位置,那就这样吧,但消除这种特殊情况会进一步降低算法的复杂性。

  • 除非您能够保留搜索结果以用于插入逻辑,否则不要搜索列表。执行链表的 O(N) 扫描以确定输入数据是否已经存在是没有意义的,只能再次搜索它 以找到所述数据实际所在的位置插入。做一次。找到它所属的位置。如果它已经在那里,什么也不做,否则,你坐在正确插入位置的悬崖边 already.

  • 最后,除非您知道自己需要,否则不要分配新节点。如果您最终什么都不做,请使用有助于自我丢弃的自动变量。

将所有这些放在一起得到如下结果:

struct CourseInfo {
    int courseID;
    char courseName[30];
};
typedef struct CourseInfo CourseInfo;

struct StudentInfo {
    char StudentID[10];
    char FirstName[21];
    char LastName[26];
    int num_course;
    CourseInfo array[10];
    struct StudentInfo *next;
};
typedef struct StudentInfo StudentInfo;

StudentInfo *addStudent(StudentInfo *head)
{
    StudentInfo **pp = &head, *p = NULL, rec;
    int knt;

    // TODO: error check your inputs!
    printf("%s", "Adding new student:\nStudent ID: ");
    scanf("%s", rec.StudentID);
    printf("%s", "First Name: ");
    scanf("%s", rec.FirstName);
    printf("%s", "Last Name: ");
    scanf("%s", rec.LastName);
    printf("%s", "Number of courses: ");
    scanf("%d", &rec.num_course);
    for(knt = 0; knt < rec.num_course; knt++) {
        printf("%s", "Course ID: ");
        scanf("%d", &rec.array[knt].courseID);
        printf("%s", "Course Name: ");
        scanf("%s", rec.array[knt].courseName);
    }

    // walk the list pointers, starting with head, looking for
    //  a node that is equal or greater than the input node
    while (*pp && (knt = strcmp((*pp)->StudentID, rec.StudentID)) < 0)
        pp = &(*pp)->next;

    // leave now if already present
    if (*pp && knt == 0)
        return head;

    // allocate new node
    p = malloc(sizeof *p);
    if (p == NULL)
    {
        perror("Failed to allocate new node");
        exit(EXIT_FAILURE);
    }

    // structure copy.
    *p = rec;

    // link into proper list position.
    p->next = *pp;
    *pp = p;

    // always return the head (which may have updated above)
    return head;
}

就是这样。如前所述,我会亲自在这个函数以外的地方执行输入操作,但我会留给你考虑。

祝你好运。