链接列表只打印列表头吗?可能覆盖列表

时间:2019-11-21 03:22:36

标签: c pointers struct linked-list

当我将学生添加到链接列表中时,将添加他们,我的计数功能将确认添加了正确数量的学生。但是,使用我的打印功能后,只会将最新的条目打印到添加的第n个学生中。可以肯定我的addStudent函数可以正常工作,但是我也可以肯定我的打印函数也是正确的。我的教授最初写的是RETURN NULL。作为addStudent函数的返回部分,但似乎不起作用,也没有将学生添加到计数或链接列表中。

Student* addStudent(Student *headStudentList, char last[], char first[])
{
    if(headStudentList == NULL){
        Student * newNode = malloc(sizeof(Student));
        newNode->firstName = first;
        newNode->lastName = last;
        newNode->next = NULL;
        headStudentList = newNode;
    }
    else {
        int check = 0;

        for(Student *cur = headStudentList; cur != NULL; cur = cur->next)
        {
            if(strcmp(first,cur->firstName)== 0 && strcmp(last, cur->lastName)== 0){
                check++;quit
            }
        }

        if (check == 0) {
            Student * newNode = malloc(sizeof(Student));
            newNode->firstName = first;
            newNode->lastName = last;
            newNode->next = headStudentList;
            headStudentList = newNode;
        }

        if (check != 0){
            printf("This Name Already Exists In The List. Enter A Different Name");
        }
    }
    return headStudentList;
}

void print(Student *headStudentList)
{
    for(Student *cur = headStudentList; cur != NULL; cur = cur->next) {
        printf("\nStudent Name: ");
        printf("%s, ", cur->lastName);
        printf("%s ", cur->firstName);
        printf("\n");
    }
    return;
}

这里是主要文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "gradebook.h"

typedef
enum {
    ADD_STUDENT,
    ADD_GRADE,
    COUNT,
    PRINT_STUDENT,
    PRINT,
    ADD_STUDENT_ORDERED,
    ADD_GRADE_ORDERED,
    REMOVE_GRADE,
    REMOVE_STUDENT,
    HELP,
    QUIT,
    INVALID
}
Option
;

char *actions[11] = {
"addStudent",
"addGrade",
"count",
"printStudent",
"print",
"addStudentOrdered",
"addGradeOrdered",
"removeGrade",
"removeStudent",
"help",
"quit"
};

int getActionID(char action[])
{
    int i;
    for (i=0; i<11; i++) {
        if (strcmp(action, actions[i])==0) return i;
    }
    return i; // 11 for invalid action
}

int isValidGradeName(char gradeName[])
{
    char type;
    int chap, sec;
    sscanf(gradeName, "%c%d.%d", &type, &chap, &sec);

    if (type!='P' && type!='C' && type!='L') return 0;
    if (chap<=0 || sec<=0) return 0;

    char name2[100];
    sprintf(name2, "%c%d.%d", type, chap, sec);
    if (strcmp(gradeName, name2)!=0) return 0;

    return 1;
}

void printHelp(void) {
    printf("\nThe valid commands:\n\n");
    printf("\taddStudent lastname firstname\n");
    printf("\t*** Add a student (add-at-front)\n");
    printf("\taddGrade lastname firstname gradename value\n");
    printf("\t*** Add a grade to an existing student (add-at-end)\n");
    printf("\tcount\n");
    printf("\t*** Print the number of students\n");
    printf("\tprintStudent lastname firstname\n");
    printf("\t*** Print a student\n");
    printf("\tprint\n");
    printf("\t*** Print all students\n");
    printf("\taddStudentOrdered lastname firstname\n");
    printf("\t*** Add a student (in alphabetical order)\n");
    printf("\taddGradeOrdered lastname firstname gradename value\n");
    printf("\t*** Add a grade in order to an existing student\n");
    printf("\tremoveGrade lastname firstname gradename\n");
    printf("\t*** Remove a grade from a student\n");
    printf("\tremoveStudent lastname firstname\n");
    printf("\t*** Remove a student\n");
    printf("\thelp\n");
    printf("\t*** Display this list\n");
    printf("\tquit\n");
    printf("\t*** Exit the program\n");

    printf("\nNote: a valid grade name starts with a letter (P, C or L),\n");
    printf("followed by a chapter number, a dot, and a section number.\n\n");
}

int main(int argc, char* argv[])
{
    char action[100];
    char last[100], first[100];
    char gradeName[100];
    double value;
    char rest[300];

    Student *headStudentList=NULL;

    while (1) {
        printf("\nEnter a command: ");
        scanf("%s", action);
        int action_id=getActionID(action);
        if (action_id==QUIT) break;
        switch (action_id) {
            case ADD_STUDENT:
                scanf("%s%s", last, first);
                headStudentList = addStudent(headStudentList, last, first);
                break;
            case ADD_GRADE:
                scanf("%s%s", last, first);
                scanf("%s", gradeName);
                if (isValidGradeName(gradeName)) {
                    scanf("%lf", &value);
                    addGrade(headStudentList, last, first, gradeName, value);
                }
                else {
                    printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
                    fgets(rest, 300, stdin); // skip the rest of line
                }
                break;
            case COUNT:
                printf("\nThere are %d students\n", count(headStudentList));
                break;
            case PRINT_STUDENT:
                scanf("%s%s", last, first);
                printStudent(headStudentList, last, first);
                break;
            case PRINT:
                print(headStudentList);
                break;
            case ADD_STUDENT_ORDERED:
                scanf("%s%s", last, first);
                headStudentList = addStudentOrdered(headStudentList, last, first);
                break;
            case ADD_GRADE_ORDERED:
                scanf("%s%s", last, first);
                scanf("%s", gradeName);
                if (isValidGradeName(gradeName)) {
                    scanf("%lf", &value);
                    addGradeOrdered(headStudentList, last, first, gradeName, value);
                }
                else {
                    printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
                    fgets(rest, 300, stdin); // skip the rest of line
                }
                break;
            case REMOVE_GRADE:
                scanf("%s%s", last, first);
                scanf("%s", gradeName);
                if (isValidGradeName(gradeName)) {
                    removeGrade(headStudentList, last, first, gradeName);
                }
                else {
                    printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
                    fgets(rest, 300, stdin); // skip the rest of line
                }
                break;
            case REMOVE_STUDENT:
                scanf("%s%s", last, first);
                headStudentList = removeStudent(headStudentList, last, first);
                break;
            case HELP:
                printHelp();
                break;
            case INVALID:
                printf("\n%s: invalid action. Type help for help.\n", action);
                fgets(rest, 300, stdin); // skip the rest of line
                break;
        }

    }
    return 0;
}

1 个答案:

答案 0 :(得分:2)

您每次都为lastfirst传递相同的数组。然后,您将此指针的值复制到每个firstName的{​​{1}}和lastName成员中。这意味着他们都指向同一个地方。然后,当您输入新的名字和姓氏时,它将覆盖以前的名字。这就是列表中所有成员都显示相同内容的原因。

您需要为每个字符串的副本分配空间,并将此空间分配给StudentfirstName。您可以使用lastName来做到这一点。

所以您在任何地方都可以这样做:

strdup

相反,这样做:

newNode->firstName = first;
newNode->lastName = last;

将学生从列表中删除后,您需要确保在致电newNode->firstName = strdup(first); newNode->lastName = strdup(last); 上的free之前先对其中的每个呼叫free