1

I have nested-structs (shown below)

in slist* add_student() I am adding new students to the list

void print_student() should print the list

void print_students(slist* students){
    slist *tempS = students;
    while(tempS){
        printf("%d:%s\n", tempS->info->id, tempS->info->name);
        tempS = tempS->next;
    }
}


slist* add_student(slist *students, char *name, int id){

    student* tempStudent;
    tempStudent =  (student *)malloc(sizeof(student));
    tempStudent->id = id;
    tempStudent->name = (char*)malloc(strlen(name)+1);
    strcpy(tempStudent->name, name);

    slist *news;
    news=(slist *)malloc(sizeof(slist));

    news->info = tempStudent;
    news->next = students;
    return news;
}

Now the problem is it is only printing the last entered "student", and I can't seem to tell which function is doing it the wrong way, so the question is, is it doing it wrong because I am using newly defined part to the struct (slist* tempS = students in void print_students()) for example? or does it have to do with the next (in both functions)?

an example of an I/O would be

and another...

The struct and main I use, if anyone wants to look at them

static void getstring(char *buf, int length) {
        int len;
        buf = fgets(buf, length, stdin);
        len = (int) strlen(buf);
        if (buf[len-1] == '\n')
            buf[len-1] = '\0';
    }
    int main() {
        slist* students = 0;

        char  c;
        char  buf[100];
        int   id, num;

        do {
            printf("Choose:\n"
                           "    add (s)tudent\n"
                           "    (p)rint lists\n"
                           "    (q)uit\n");

            while ((c = (char) getchar()) == '\n');
            getchar();

            switch (c) {
            case 's':
                printf("Adding new student.\n");

                printf("Student name: ");
                getstring(buf, 100);

                printf("Student ID: ");
                scanf("%d", &id);

                students = add_student(students, buf, id);

                break;
            case 'p':
                printf("Printing Information.\n");
                print_students(students);
                break;
            }

            if (c != 'q')
                printf("\n");
        } while (c != 'q');
        return 0;
    }


 // structures
    typedef struct student {
        char *name;
        int  id;
        struct clist *courses;
    } student;

    typedef struct course {
        char *title;
        int  number;
        struct slist *students;
    } course;

    typedef struct slist {
        student      *info;
        struct slist *next;
    } slist;

    typedef struct clist {
        course       *info;
        struct clist *next;
    } clist;
gsamaras
  • 71,951
  • 46
  • 188
  • 305

1 Answers1

1

In general, pick up a piece of paper and a pencil and draw what your code does; that's a pro tip for finding what's wrong with your list when in trouble!


Your code is fine* now, and let me explain you why.

So, if you do so you will see that when the first student arrives, you allocate space for him/her and then populate that struct correctly. tempStudent points to that struct.

Then, news will create a new struct that is the struct that handles the list. Its info field is set to the newly created student and next points to students, which I guess is NULL when the first student is added.

Then you return news and students now points to it.


Now we are about to add the second student. We create his struct - so far so good!

We again create the struct news which handles the list. It will assign info to newly created student and next will point to students, which is what we want.

Then you return news and students now points to it.

That way of course the newly created student will be places first in the list, despite the fact we added him/her secondly.


As a result, you will get something like this:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
Choose:
    add (s)tudent
    (p)rint lists
    (q)uit
s
Adding new student.
Student name: Leon
Student ID: 1

Choose:
    add (s)tudent
    (p)rint lists
    (q)uit
s
Adding new student.
Student name: kate
Student ID: 2

Choose:
    add (s)tudent
    (p)rint lists
    (q)uit
p
Printing Information.
2:kate
1:Leon

which is OK.


*Of course you have to write other functions as well, such as deleting your list and de-allocating the space you already allocated.

Do I cast the result of malloc? No!

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305