1

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;
}
6
  • You need to give us a fully functional program that demonstrates the problem. In particular, need the code that calls these functions. I suspect the problem is this: newNode->firstName = first;. Probably should be making a copy of the name strings. But can't be sure because you have not provided complete code. Commented Nov 21, 2019 at 3:27
  • where is your student struct? Commented Nov 21, 2019 at 3:29
  • What is quit? Commented Nov 21, 2019 at 3:31
  • 2
    Yeah as I suspected, that is the problem. The calling code passes in the same last and first buffers each time (with different contents). You need to make a copy of those. Commented Nov 21, 2019 at 3:32
  • 1
    The list isn't the problem, the problem is that the list elements all contain the same strings. Commented Nov 21, 2019 at 3:34

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.