Stephen Carson
Stephen Carson

Reputation: 25

Linked list only printing the head of list? Possibly overwriting list

When I add Students to the the linked list they are added and my count function will confirm the correct amount of students are added. However, upon using my print function, only the latest entry will be printed to the nth amount of students added. Fairly certain my addStudent function is working correctly but I am also fairly certain my print function is correct as well. My professor originally wrote RETURN NULL; as the return part of the addStudent function but that doesnt seem to work and doesnt add students to the count or linked list.

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

HERE IS THE MAIN FILE

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

Upvotes: 1

Views: 66

Answers (1)

dbush
dbush

Reputation: 223787

You're passing the same array for last and first each time. You then copy the value of this pointer to the firstName and lastName members of each Student. This means that all of them are pointing to the same place. Then when you read in a new first and last name it overwrites what was there previously. This is why all members of the list are showing the same thing.

You need to allocate space for a copy of each of these strings and assign this space to firstName and lastName. You can do this with strdup.

So anyplace you do this:

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

Instead do this:

newNode->firstName = strdup(first);
newNode->lastName = strdup(last);

When you remove a student from the list, you'll need to make sure you call free on each of these before calling free on the Student.

Upvotes: 2

Related Questions