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?
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?
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
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.
Is this correct I declare it?
And why in function below my program get errorCode: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; }
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); }
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.
I already tried it
I changedCode:strcpy(newNode->nama,*nama); strcpy(newNode->nim,*nim);It always make my program crashed when I try to input *nama. Am I using it wrong? I am firstly using this function.
to
Code:newNode->nama=strdup(*nama); newNode->nim=strdup(*nim);
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.
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.
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; }
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.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; };
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:
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.Originally Posted by Subsonics
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.
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
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:
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.Code:struct node { void *data; struct node *next; }
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.
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.
and this is how I pass it and used it in my mainCode: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; } }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;
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.
This is my full code. Ignore the munu function for now.
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 anythingCode:#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; }