Thread: Declaring linked list inside linked list

  1. #1
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22

    Declaring linked list inside linked list

    I got confused in my program. I want to make a struct class which is linked list and then inside it I want to have another struct called student. Can I declare struct student as a linked list too? How to access it?

  2. #2
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by blueboyz View Post
    Can I declare struct student as a linked list too? How to access it?
    You wouldn't need to declare it as a linked list. A list node in a singly linked list consist of a payload or data and a link. You just need to make you data part of your list node be a struct student, or a pointer to one.

    Code:
    struct student {
       char *name;
       int age;
    };
    
    struct node {
       struct student student;
       struct node *next;
    };
    
    // you can then access it like this (assuming your list is called list).
    
    list->student.name
    list->student.age

  3. #3
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    Then how if I want to add new struct student? If I declare it like that, doesn't it means for making new struct student I need to make new struct node right?

  4. #4
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by blueboyz View Post
    Then how if I want to add new struct student? If I declare it like that, doesn't it means for making new struct student I need to make new struct node right?
    Yes it does, in the example above each struct node has an embedded struct student. It's a bit simpler in terms of memory management to only have one object, the node it self to take care about.

    But you can also make the first member a pointer to struct student like I mentioned in the first post. Just add a * in the node example above. Then you can allocate memory for a new struct student, then assign the pointer to your list->student pointer.

  5. #5
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    Is this correct I declare it?
    Code:
    typedef struct mhs mhs;
    typedef struct kelas kelas;
    
    
    struct mhs
    {
        char *nama;
        char *nim;
        int angkatan;
        float ipk;
        mhs *next1;
    };
    
    
    struct kelas
    {
        char *kls;
        int jml;
        mhs mhs;
        kelas *next;
        mhs *head1;
    };
    
    
    kelas *head;
    mhs *head1;
    int nodeKelas;
    
    
    void init()
    {
        head=NULL;
        head1=NULL;
        nodeKelas=0;
    }
    And why in function below my program get error

    Code:
    int insertMhs(char **klas,char **nama,char **nim,int angkatan,float ipk,int banyak)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            if(strcmp(itr->kls,*klas)==0)
            {
                mhs *itr1=head1;
                mhs *newNode=(mhs*)malloc(sizeof(mhs));
                strcpy(newNode->nama,*nama);
                strcpy(newNode->nim,*nim);
                newNode->angkatan=angkatan;
                newNode->ipk=ipk;
                itr->jml++;
                newNode->next1=head1;
                head1=newNode;
                return 1;
            }
            else printf("Nama kelas yang anda masukkan tidak ada\n");
            itr=itr->next;
            return 0;
        }

    this is how I called the function
    Code:
    fflush(stdin);
                printf("Memasukkan di kelas\t:");gets(tesKelas);
                int jml,i,angkatanMhs;
                float ipkMhs;
                char *namaMhs,*nimMhs;
                printf("Jumlah mahasiswa yang ingin anda masukkan di kelas %s \t",tesKelas);scanf("%d",&jml);
                for(i=0;i<jml;i++)
                {
                    printf("%d.\tNama\t: ",i+1);fflush(stdin);gets(namaMhs);
                    printf("  \tNIM\t: ");fflush(stdin);gets(nimMhs);
                    printf("  \tAngkatan tahun\t: ");fflush(stdin);scanf("%d",&angkatanMhs);
                    printf("  \tIPK\t: ");fflush(stdin);scanf("%f",&ipkMhs);
                    insertMhs(&tesKelas,&namaMhs,&nimMhs,angkatanMhs,ipkMhs,jml);
                }

  6. #6
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by blueboyz View Post
    Code:
                strcpy(newNode->nama,*nama);
                strcpy(newNode->nim,*nim);
    There might be other problems but these lines will not work because in your struct mhs both nama and nim are only pointers. That is, they can hold an address where the string can be found. You can not use strcpy with these since all you have is a pointer.

    If you have strdup() available, it makes this easy, other alternative is to create you own strdup() which basically only mallocs strlen() + 1 characters, call strcpy() and returns the new fresh string. One last alternative is to declare nama and nim as arrays, the limitation there is that you are either wasting space or lack space unless your strings are exactly the length in the declaration.

    If you go for allocating dynamically, create, create_node()/ free_node() functions as it simplifies memory management, in the free_node() function you would first free all strings and finnish off by freeing the node itself.

  7. #7
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    I already tried it
    I changed
    Code:
    strcpy(newNode->nama,*nama); strcpy(newNode->nim,*nim);

    to
    Code:
    newNode->nama=strdup(*nama);
    newNode->nim=strdup(*nim);
    It always make my program crashed when I try to input *nama. Am I using it wrong? I am firstly using this function.

    Anyway why my strcmp in the function insertMhs can't be used correctly?
    Whatever input klas I type, even it doesn't exist in kelas->kls it doesn't directly exit program.

  8. #8
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    If you look where *nama originates from, it's supplied as an argument in the form of the variable *namaMhs. Again it's the same problem, *namaHhs is just pointer so you can not use gets on it (you should use fgets instead btw). If you declare namaHhs as: char namaHhs[BUFSIZ] (or some other size) then fgets(namaHhs, BUFSIZ, stdin); you have a temporary storage that you can pass to the function.

    The reason strcmp does not work relates to the same thing if you look at head, you'll see that it is once again nothing but a pointer unless you allocate memory for head somewhere in some code that you have not posted.

  9. #9
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    Well I declare char as pointer in order to make it accept no matter how many the length of the string. Can you help me how to accept any length of string?
    Anyway, this is my code. I hope you can fix function insertMhs too. It will crash the program after I input it. And is my freeMemory good?

    Code:
    \#include <stdio.h>#include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #include <windows.h>
    
    
    typedef struct mhs mhs;
    typedef struct kelas kelas;
    
    
    struct mhs
    {
        char *nama;
        char *nim;
        int angkatan;
        float ipk;
        mhs *next1;
    };
    
    
    struct kelas
    {
        char *kls;
        int jml;
        mhs mhs;
        kelas *next;
        mhs *head1;
    };
    
    
    kelas *head;
    mhs *head1;
    int nodeKelas;
    
    
    void init()
    {
        head=NULL;
        head1=NULL;
        nodeKelas=0;
    }
    
    
    int menu()
    {
        int pil;
        printf("\t\t------------------------\n");
        printf("\t\t|Program Data Mahasiswa|\n");
        printf("\t\t------------------------\n\n\n");
        printf("1. Menambah kelas\n");
        printf("2. Memasukkan data mahasiswa\n");
        printf("3. Menghapus data mahasiswa\n");
        printf("4. Input data dari file\n");
        printf("5. Tulis ke dalam file\n");
        printf("Masukkan pilihan anda : ");scanf("%d",&pil);
        return pil;
    }
    
    
    
    
    int insertKelas(const char *klas)
    {
       kelas *newNode = (kelas*) malloc(sizeof(kelas));
       if(newNode != NULL)
       {
          strcpy(newNode->kls,klas);
          newNode->jml=0;
          newNode->next=head;
          head=newNode;
          nodeKelas++;
          return 1;
       }
       else return 0;
    }
    
    
    int insertMhs(const char *klas,char *nama,char *nim,int angkatan,float ipk,int banyak)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            if(strcmp(itr->kls,klas)==0)
            {
                mhs *itr1=head1;
                mhs *nodeBaru=(mhs*)malloc(sizeof(mhs));
                strcpy(nodeBaru->nama,nama);
                strcpy(nodeBaru->nim,nim);
                nodeBaru->angkatan=angkatan;
                nodeBaru->ipk=ipk;
                itr->jml++;
                nodeBaru->next1=head1;
                head1=nodeBaru;
                return 1;
            }
            else printf("Nama kelas yang anda masukkan tidak ada\n");
            itr=itr->next;
            return 0;
        }
    }
    
    
    
    
    void printList()
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            printf("Jumlah kelas\t: %d\n",nodeKelas);
            printf("Kelas\t: %s\n",itr->kls);
            printf("Jumlah\t: %d\n",itr->jml);
            mhs *itr1=head1;
            while(itr1!=NULL)
            {
                printf("%s\n", itr1->nama);
                printf("%s\n",itr1->nim);
                printf("%d\n",itr1->angkatan);
                printf("%.2f\n\n",itr1->ipk);
                itr1=itr1->next1;
            }
            itr = itr->next;
        }
    }
    
    
    void freeMemory()
    {
        kelas *hapus;
        while (head!=NULL)
        {
            mhs *deleteNode;
            while (head1 != NULL)
            {
                deleteNode = head1;
                head1 = head1->next1;
                free(deleteNode);
            }
            hapus=head;
            head=head->next;
            free(hapus);
        }
    }
    
    
    int main()
    {
       int pil;
       char namaKelas[10],tesKelas[10];
       tes:
       system("CLS");
       pil=menu();
       switch (pil)
       {
          case 1:
                printf("Menambah kelas\t: ");fflush(stdin);fgets(namaKelas,10,stdin);
                insertKelas(namaKelas);
                goto tes;
                break;
          case 2:
                printf("Memasukkan di kelas\t:");fflush(stdin);fgets(tesKelas,10,stdin);
                int jml,i,angkatanMhs;
                float ipkMhs;
                char namaMhs[30],nimMhs[15];
                printf("Jumlah mahasiswa yang ingin anda masukkan di kelas %s \t",tesKelas);scanf("%d",&jml);
                for(i=0;i<jml;i++)
                {
                    printf("%d. Nama\t\t: ",i+1);fflush(stdin);fgets(namaMhs,30,stdin);
                    printf("   NIM\t\t: ");fflush(stdin);fgets(nimMhs,15,stdin);
                    printf("   Angkatan tahun\t: ");fflush(stdin);scanf("%d",&angkatanMhs);
                    printf("   IPK\t\t: ");fflush(stdin);scanf("%f",&ipkMhs);
                    insertMhs(tesKelas,namaMhs,nimMhs,angkatanMhs,ipkMhs,jml);
                }
                goto tes;
                break;
            case 3:
                printList();
                getch();
                goto tes;
                break;
            default:
                return 0;
       }
            freeMemory();
            getch();
            return 0;
    }

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Code:
    struct mhs
    {
        char *nama;
        char *nim;
        int angkatan;
        float ipk;
        mhs *next1;
    };
     
     
    struct kelas
    {
        char *kls;
        int jml;
        mhs mhs;
        kelas *next;
        mhs *head1;
    };
    Are these two structures meant to be separate lists? If it isn't meant to be separate lists, I don't think you've been following Subsonics' advice.

    The idea was to create a structure representing a student, with all the data associated with coursework. And there would be a separate list node structure which contains a single student and the next link inside. You would link together instances of the list node structure (i.e., variables of that type). In this way you create a linked list that contains all of your students.

    If we look at Subsonics example again:
    Quote Originally Posted by Subsonics
    Code:
    struct student {
       char *name;
       int age;
    };
     
    struct node {
       struct student student;
       struct node *next;
    };
     
    // you can then access it like this (assuming your list is called list).
     
    list->student.name
    list->student.age
    List is the head, list->next is the next node, and so on. You would fill in list->student, and list->next->student, and so on.

    It's a bit hard for me to tell what's going on because I don't speak your language and the variables are alphabet soup, so I'm sorry if that sounds confusing. But if you apply some intelligence I think you'll get what I'm saying.

  11. #11
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    I am already declare it like subsonics advice. Looks in
    mhs mhs


    Isn't that what subsonics advice? I use mhs mhs because I already typedef struct mhs to mhs
    So i called it as mhs mhs

  12. #12
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    It still looks like both your structs contains links to other structs of the same type, it also look like both your insert functions link to other nodes. A list node could be declared like this:

    Code:
    struct node {
        void *data;
        struct node *next;
    }
    The node (which you list consists of) have no idea about what *data is. All functions that operates on the list are only concerned with linking to other nodes and inserting/returning the *data pointer.

    Your student struct does not have to deal with links, or any concept of a list. You create a new struct student, fill it up (in your case from stdin) and pass it to a list_insert function which just assigns it to the *data pointer.
    Last edited by Subsonics; 04-15-2012 at 09:45 PM.

  13. #13
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    Can you explain it more detailed? I bit confused with void *data. With an example of program maybe?

    Anyway I managed it somehow to passing data to student and node with allocate length of string. But I got a problem. It will also write student in another node. Here is the code which I used.
    Code:
    
    int cocokKelas(char *klas)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            if(strcmp(itr->kls,klas)!=0) itr=itr->next;
            else return 1;
        }
    }
    
    
    int insertMhs(char *klas,char *nama,char *nim,int angkatan,float ipk)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            if(strcmp(itr->kls,klas)==0)
            {
                mhs *itr1=head1;
                mhs *nodeBaru=(mhs*)malloc(sizeof(mhs));
                strcpy(nodeBaru->nama,nama);
                strcpy(nodeBaru->nim,nim);
                nodeBaru->angkatan=angkatan;
                nodeBaru->ipk=ipk;
                itr->jml++;
                nodeBaru->next1=head1;
                head1=nodeBaru;
            }
            itr=itr->next;
        }
    }
    
    
    
    
    void printList()
    {
        kelas *itr = head;
        printf("Jumlah kelas\t: %d\n\n",nodeKelas);
        while (itr != NULL)
        {
            printf("Kelas\t\t: %s",itr->kls);
            printf("Jumlah\t\t: %d\n",itr->jml);
            mhs *itr1=head1;
            while(itr1!=NULL)
            {
                int i=1;
                printf("%d. Mahasiswa\t: %s",i, itr1->nama);
                printf("   NIM\t\t: %s",itr1->nim);
                printf("   Angkatan\t: %d\n",itr1->angkatan);
                printf("   IPK\t\t: %.2f\n\n",itr1->ipk);
                itr1=itr1->next1;
                i++;
            }
            itr = itr->next;
        }
    }
    and this is how I pass it and used it in my main
    Code:
    case 2:
                printf("Memasukkan di kelas\t:");fflush(stdin);fgets(tesKelas,15,stdin);
                int cocok=cocokKelas(tesKelas);
                if(cocok==1)
                {
                    int jml,i,angkatanMhs;
                    float ipkMhs;
                    char namaMhs[30],nimMhs[15];
                    printf("Jumlah mahasiswa yang ingin anda masukkan di kelas %s \t",tesKelas);scanf("%d",&jml);
                    for(i=0;i<jml;i++)
                    {
                        printf("%d. Nama\t\t: ",i+1);fflush(stdin);fgets(namaMhs,30,stdin);
                        printf("   NIM\t\t: ");fflush(stdin);fgets(nimMhs,15,stdin);
                        printf("   Angkatan\t: ");fflush(stdin);scanf("%d",&angkatanMhs);
                        printf("   IPK\t\t: ");fflush(stdin);scanf("%f",&ipkMhs);
                        insertMhs(tesKelas,namaMhs,nimMhs,angkatanMhs,ipkMhs);
                    }
                    goto tes;
                }
                else printf("Nama Kelas yang anda masukkan tidak ada\n");
                goto tes;
                break;

  14. #14
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    You don't have student member in the node. You have a POINTER to a student. You still obviously don't understand how linked lists work.

    Imagine you have a mailbox in front of your house. In that mailbox, you have a letter(the data) and you have a small note that gives you a new postcode (the pointer to the next mailbox). You read the note, go to that post code open the mailbox. In the mailbox you find a letter and another small note giving you the postcode of the next mailbox, and so on.

    You don't have a mailbox inside a mailbox, you have the address of the next mailbox.

    As for other things wrong with your code that can be and should be fixed before proceeding:

    1) Don't cast the return value of malloc.

    2) Don't fflush(stdin) that's undefined behaviour on any standard abiding implementation.

    3) Don't use goto! Goto should be used sparingly and there is absolutely no need for it in your code.

    4) POST YOUR ENTIRE CODE
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  15. #15
    Registered User
    Join Date
    Apr 2012
    Location
    Malang, Indonesia
    Posts
    22
    This is my full code. Ignore the munu function for now.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    
    
    typedef struct mhs mhs;
    typedef struct kelas kelas;
    
    
    struct mhs
    {
        char nama[30];
        char nim[15];
        int angkatan;
        float ipk;
        mhs *next1;
    };
    
    
    struct kelas
    {
        char kls[15];
        int jml;
        mhs *mhs;
        kelas *next;
        mhs *head1;
    };
    
    
    kelas *head;
    mhs *head1;
    int nodeKelas;
    
    
    void init()
    {
        head=NULL;
        head1=NULL;
        nodeKelas=0;
    }
    
    
    int menu()
    {
        int pil;
        printf("\t\t------------------------\n");
        printf("\t\t|Program Data Mahasiswa|\n");
        printf("\t\t------------------------\n\n\n");
        printf("1. Menambah kelas\n");
        printf("2. Memasukkan data mahasiswa\n");
        printf("3. Mencetak kelas\n");
        printf("4. Input data dari file\n");
        printf("5. Tulis ke dalam file\n");
        printf("Masukkan pilihan anda : ");scanf("%d",&pil);
        return pil;
    }
    
    
    
    
    int insertKelas(char *namaKelas)
    {
       kelas *newNode = (kelas*) malloc(sizeof(kelas));
       if(newNode != NULL)
       {
          strcpy(newNode->kls,namaKelas);
          newNode->jml=0;
          newNode->next=head;
          head=newNode;
          nodeKelas++;
          return 1;
       }
       else return 0;
    }
    
    
    int cocokKelas(char *klas)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            if(strcmp(itr->kls,klas)==0) return 1;
            else itr=itr->next;
        }
    }
    
    
    int insertMhs(char *nama,char *nim,int angkatan,float ipk)
    {
        kelas *itr = head;
        while (itr != NULL)
        {
            //if(strcmp(itr->kls,klas)==0)
            //{
                //mhs *itr1=head1;
                mhs *nodeBaru=(mhs*)malloc(sizeof(mhs));
                strcpy(nodeBaru->nama,nama);
                strcpy(nodeBaru->nim,nim);
                nodeBaru->angkatan=angkatan;
                nodeBaru->ipk=ipk;
                itr->jml++;
                nodeBaru->next1=head1;
                head1=nodeBaru;
            //}
            itr=itr->next;
        }
    }
    
    
    
    
    void printList()
    {
        kelas *itr = head;
        printf("Jumlah kelas\t: %d\n\n",nodeKelas);
        while (itr != NULL)
        {
            printf("Kelas\t\t: %s",itr->kls);
            printf("Jumlah\t\t: %d\n",itr->jml);
            mhs *itr1=head1;
            while(itr1!=NULL)
            {
                int i=1;
                printf("%d. Mahasiswa\t: %s",i, itr1->nama);
                printf("   NIM\t\t: %s",itr1->nim);
                printf("   Angkatan\t: %d\n",itr1->angkatan);
                printf("   IPK\t\t: %.2f\n\n",itr1->ipk);
                itr1=itr1->next1;
                i++;
            }
            itr = itr->next;
        }
    }
    
    
    void freeMemory()
    {
        kelas *hapus;
        while (head!=NULL)
        {
            mhs *deleteNode;
            while (head1 != NULL)
            {
                deleteNode = head1;
                head1 = head1->next1;
                free(deleteNode);
            }
            hapus=head;
            head=head->next;
            free(hapus);
        }
    }
    
    
    int main()
    {
       int pil=0;
       char namaKelas[15],tesKelas[15];
       init();
       do
       {
            system("CLS");
            pil=menu();
            switch (pil)
            {
                case 1:
                    system("CLS");
                    printf("Menambah kelas\t: ");fflush(stdin);
                    fgets(namaKelas,15,stdin);
                    insertKelas(namaKelas);
                    break;
                case 2:
                    system("CLS");
                    printf("Memasukkan di kelas\t:");fflush(stdin);
                    fgets(tesKelas,15,stdin);
                    int cocok=cocokKelas(tesKelas);
                    if(cocok==1)
                    {
                        int jml,i,angkatanMhs;
                        float ipkMhs;
                        char namaMhs[30],nimMhs[15];
                        printf("Jumlah mahasiswa yang ingin anda masukkan di kelas %s \t",tesKelas);scanf("%d",&jml);
                        for(i=0;i<jml;i++)
                        {
                            printf("%d. Nama\t\t: ",i+1);fflush(stdin);
                            fgets(namaMhs,30,stdin);
                            printf("   NIM\t\t: ");fflush(stdin);
                            fgets(nimMhs,15,stdin);
                            printf("   Angkatan\t: ");fflush(stdin);
                            scanf("%d",&angkatanMhs);
                            printf("   IPK\t\t: ");fflush(stdin);
                            scanf("%f",&ipkMhs);
                            insertMhs(namaMhs,nimMhs,angkatanMhs,ipkMhs);
                        }
                    }
                    else printf("Nama Kelas yang anda masukkan tidak ada\n");
                    break;
                case 3:
                    system("CLS");
                    printList();
                    getch();
                    break;
                default:
                    return 0;
            }
        }while(pil<=3);
        freeMemory();
        return 0;
    }
    Btw, what do youi mean with point number 1? And in point number 2 if I don't use fflush(stdin), I don't know why I can't input anything

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. linked list inside a structure
    By jerepops in forum C Programming
    Replies: 5
    Last Post: 12-14-2009, 08:22 PM
  2. Linked List inside Linked List
    By de4th in forum C++ Programming
    Replies: 1
    Last Post: 05-15-2006, 11:17 AM
  3. singly linked list to doubly linked list
    By t48j in forum C Programming
    Replies: 3
    Last Post: 03-23-2005, 06:37 PM
  4. Replies: 6
    Last Post: 03-02-2005, 02:45 AM
  5. linked list inside array of structs- Syntax question
    By rasmith1955 in forum C Programming
    Replies: 14
    Last Post: 02-28-2005, 05:16 PM