allocating in heap memory array of pointers to struct - c

I'm trying to make simple data base by using structure like
struct Employee{
char* name;
int ID;
int GPA;
int salary;
};
i know how i can allocate one pointer of the struct type in heap by using that
struct Employee* emp=malloc(sizeof(Employee));
my problem now that i'm not very good in allocating processes and i want
to allocate N number of pointer of the struct in the heap and i can't use arrays because the size will not be knows until running time
any suggestions ?

Yes, you need to allocate the memory dynamically, i.e. allocate a new heap block for every new struct Employee.
You can do this for example using realloc when the size changes:
yourArrayPtr=realloc(yourArrayPtr,newsize * sizeof(struct Employee));
The realloc function basically assigns a new amount of memory for the data pointed by its return value. It is a convenient way of expanding, or shrinking a dynamically allocated array. newsize here is the new number of elements of your array, and it is multiplied by the size of one Employee structure, rendering the total amount of space needed for your new array. The return value of realloc is assigned to your array pointer, so that it points specifically to this newly allocated space. In this case it could be used like this:
struct Employee* emp= NULL;
And then when you need it:
int n = 8;
emp = realloc (emp, n * sizeof(struct Employee));
Keep in mind, that you still have to free this memory.
You can now initialize and access this data:
emp[3] = {value1, value2, value3, ...};
As far as structures go, you could also think of another data structure - a linked list, where every structure contains a pointer to its successor. You can read about it here: http://www.cprogramming.com/tutorial/c/lesson15.html
In your case, it would be sth like:
struct Employee{
char* data;
struct Employee* next;
};

As others mentioned, you can use malloc to create as many entries of employee details in heap and store them in a dynamic list(linked list). i have given an example code, you can start from here and extend it, if you want to save the employee details before exiting, you can write it to a binary file and read it back when you run the program again(based on your needs), since once you program exits all the data will be lost.
#include <stdio.h>
#include <stdlib.h>
// Max length for employee name
const unsigned int MAX_NAME_LEN = 100;
typedef struct Employee{
char* name;
unsigned int ID;
int GPA;
float salary;
} EMPLOYEE ;
typedef struct emp_database_entry {
EMPLOYEE data;
struct emp_database_entry *next;
} EMPLOYEE_ENTRY;
typedef EMPLOYEE_ENTRY* EMPLOYEE_DATABASE;
// to create a new employee
EMPLOYEE_ENTRY* createEmployee() {
EMPLOYEE_ENTRY *newEmp = (EMPLOYEE_ENTRY*)malloc(sizeof(EMPLOYEE_ENTRY));
printf("Enter Employee Name:");
newEmp->data.name = (char*)malloc( MAX_NAME_LEN * sizeof(char) );
scanf("%s",newEmp->data.name);
printf("Enter employee ID:");
scanf("%u",&newEmp->data.ID);
printf("Enter employee GPA:");
scanf("%u",&newEmp->data.GPA);
printf("Enter employee salary:");
scanf("%f",&newEmp->data.salary);
newEmp->next = 0;
return (newEmp);
}
// add a new employee to database
EMPLOYEE_DATABASE addEmployee(EMPLOYEE_DATABASE db) {
EMPLOYEE_ENTRY *newEmp = createEmployee();
if(db == NULL) {
// add the first entry
db = newEmp;
} else {
// add it to the top
newEmp->next = db;
db = newEmp;
}
return (db);
}
// Search for Employee using ID
EMPLOYEE_ENTRY* searchEmployee(EMPLOYEE_DATABASE db, unsigned int ID) {
EMPLOYEE_ENTRY *employee = db;
if(employee == NULL) {
printf("There are no Employees in the database\n");
return (NULL);
}
// Search till the end, if a match is found return the
// pointer to employee
while( employee != NULL ) {
if( employee->data.ID == ID )
return (employee);
else
employee = employee->next;
}
return (NULL);
}
void printOneEmployee( EMPLOYEE_ENTRY *employee ) {
printf("Employee Details\n");
printf("Name : %s\n",employee->data.name);
printf("ID : %u\n",employee->data.ID);
printf("GPA : %d\n",employee->data.GPA);
printf("Salary: %f\n\n",employee->data.salary);
}
// Print all employee details
void printAllEmployee( EMPLOYEE_DATABASE db ) {
EMPLOYEE_ENTRY *employee = db;
// traverse till the end and print one by one
while( employee != NULL ) {
printOneEmployee(employee);
employee = employee->next;
}
}
// freeing allocated memory
void freeDatabase(EMPLOYEE_DATABASE db) {
EMPLOYEE_DATABASE employee = 0;
while( db != NULL ) {
employee = db;
db = employee->next;
free(employee->data.name);
free(employee);
}
}
void displayOption( EMPLOYEE_DATABASE db ) {
int option = -1;
while( option != 5 ) {
printf("\nEmployee DataBase\n");
printf("1: Add a Employee\n");
printf("2: Search Employee\n");
printf("3: Print All Employee\n");
printf("4: Exit\n");
printf("Enter a number for the choice: ");
scanf("%d",&option);
if( option > 4 || option < 0 ) {
option = -1;
}
switch( option ) {
case 1:
db = addEmployee(db);
break;
case 2:
int ID;
if(db != NULL){
printf("Enter the Employee ID: ");
scanf("%d",&ID);
printf("Search Result1: ");
printOneEmployee(searchEmployee(db, ID));
}
else
printf("No Employees in the database\n");
break;
case 3:
printAllEmployee(db);
break;
case 4:
freeDatabase(db);
printf("DataBase Deleted\nExiting..");
exit(0);
default:
printf("Invalid Option!. Try Again!.\n");
}
}
}
int main() {
EMPLOYEE_DATABASE db = 0;
displayOption(db);
return (0);
}

Of course you can use arrays if you use C99. In C99 you can do things like:
scanf("%d", &N);
struct Employee emp[N];
emp[0].ID = 123;
if you are using gcc (or MinGW), just be sure to compile with -std=c99
On the other hand, if you just want to create an array on the heap, you can do something like:
scanf("%d", &N);
struct Employee* emp=malloc(N*sizeof(Employee));
emp[0].ID =123;
...
// do not forget to deallocate emp
free(emp);

Related

How to assign a value to a struct that is returned through a function in C

extern int ID; // student ID number
struct personalDetails det; // pD
struct classRecords rec; // cR
struct student st1; // student 1
struct student st2; // student 2
struct student st3; // student 3
struct student st4; // student 4
struct student st5; // student 5
char pD[30]; // for storing values that will be assigned to personalDetails
double cR; // for storing values that will be assigned to classRecords
struct student studentID(int id) { // identifies student by ID
if (id == 1) {
struct student x = st1;
return x;
}
else if (id == 2) {
struct student x = st2;
return x;
}
else if (id == 3) {
struct student x = st3;
return x;
}
else if (id == 4) {
struct student x = st4;
return x;
}
else if (id == 5) {
struct student x = st5;
return x;
}
}
I need the function updateName() to assign a value to 'name' which is a value within another struct personalDetails.
void updateName() {
printf("Enter student's name\n");
scanf("%s", pD);
studentID(ID).det.name = pD;
I'm currently getting this error:
operations.c: In function ‘updateName’:
operations.c:55:24: error: lvalue required as left operand of assignment
studentID(ID).det.name = pD;
Please tell me how I can fix this, thanks in advance!
EDIT 1: Here's the struct defs for those interested.
struct personalDetails {
char *name;
char *phoneNum;
char *address;
};
struct classRecords {
double assignment;
double midterm;
double finalMark;
double total;
};
struct student{
struct personalDetails det;
struct classRecords rec;
};
Thanks for the answers, strcpy got rid of the compilation error, but now when I enter a value for 'name' I get a 'segmentation fault'. Anyone know why?
studentID(ID) returns a copy of the structure where you store the data, that you need to store into another structure. You probably want to return a pointer to it and use this syntax:
strcpy(studentID(ID)->det.name, pD);
But you should also pay attention to potential buffer overflows: for example, scanf with a %s format does not know the size of the array pointed to by pD. You should write this instead:
scanf("%29s", pD);
But telling scanf about buffer sizes is very cumbersome as the size information must be hard coded in the format string and may become out of sync if you later change the actual size of the array pD. scanf is very tricky to use correctly.
C does not allow you to directly assign strings using the equal operator. You can use strncpy (include string.h). Read about the function by typing 'man strncpy' in the terminal or googling it.
You haven't shown your struct student declaration; but looks like name is a character array. Then,
scanf("%s", &pD); is incorrect, should be scanf("%s", pD); as pD is already the address of the string character.
Also, studentID(ID).det.name = pD; is incorrect as well, you can't use direct assignment for string variable, use strcpy instead.
I guess you want something like this. Use pointers.
extern int ID; // student ID number
struct personalDetails det; // pD
struct classRecords rec; // cR
struct student st1; // student 1
struct student st2; // student 2
struct student st3; // student 3
struct student st4; // student 4
struct student st5; // student 5
char pD[30]; // for storing values that will be assigned to personalDetails
double cR; // for storing values that will be assigned to classRecords
struct student *studentID(int id) { // identifies student by ID
if (id == 1) {
return &st1;
}
else if (id == 2) {
return &st2;
}
else if (id == 3) {
return &st3;
}
else if (id == 4) {
return &st4;
}
else if (id == 5) {
return &st5;
}
}
void updateName() {
struce student *s;
printf("Enter student's name\n");
scanf("%29s", pD);
s = studentID(ID);
s->det.name = malloc(strlen(pD) + 1);
strcpy(s->det.name, pD);
}
I'm not sure if this is correct because I don't know the definition of struct student, but please don't do such a foolish thing as assigning a (pointer to the first element of) fixed array to multiple structs.

Adding records with pointers to arrays

I have to create a program which adds records to a simple phone book. The code is below, but it doesn't work - function ends and then it stucks on declaring struct record x and doesn't want to display my added record - the program breaks down. When I put this part of code on the end of the function (but instead of "struct record x = array[0];" I put "struct record x = (*array)[0]") it works - record is printed. So I guess the problem is something about pointers, but I'm struggling and I really couldn't find out what's wrong. I remember that few weeks ago I created a program which was very similar but it was adding a new record to an array of integers, with fixed values and it was working well, so maybe there's something with structures that I don't know about. Thanks for any help!
I know the program isn't done yet and I know that I didn't make any action for temp_array == NULL, it'll be done after I found out what's going on.
struct record {
char f_name[SIZE];
char name[SIZE];
long int phone;
};
int add_record(struct record** array, int n)
{
struct record* temp_array = malloc((n+1) * sizeof(struct record));
if (temp_array == NULL)
{
free(temp_array);
return -1;
}
int i;
for (i=0; i < n; i++)
{
temp_array[i] = (*array)[i];
}
struct record new_record;
printf("\nAplly data.");
printf("\nFirst name: "); /*fgets(new_record.f_name, SIZE, stdin);*/ scanf("%s", &new_record.f_name);
printf("Surname: "); /*fgets(new_record.name, SIZE, stdin);*/ scanf("%s", &new_record.name);
printf("Phone number: "); scanf("%d", &new_record.phone);
temp_array[n] = new_record;
free (*array);
*array = temp_array;
//struct record x = (*array)[0];
//puts(x.f_name); puts(x.name); printf("%d", x.phone);
return 0;
}
main()
{
struct record* array; int n = 0;
int choice;
printf("\n1. Add record\n2. Delete record\n3. Find record\n0. Exit\n\nChoose action: ");
scanf("%d", &choice);
switch(choice) {
case 0: printf("\nKsiazka zostala zamknieta.\n"); return;
case 1: add_record(&array, n); n++; break;
case 2: return;
case 3: return;
default: printf("Wrong choice.\n\n"); return;
}
struct record x = array[0];
puts(x.f_name); puts(x.name); printf("%d", x.phone);
}
struct record* array=NULL;, and use %ld for long int – BLUEPIXY

Seg Fault in my

I have an issue with my code here when I try to add a record to the database. Everytime I enter anything more than a few characters in for the first name prompt, the program will seg fault, even after moving elements from the old record. I understand that seg faults are due to trying to access memory that we don't have access too, but for the life of me I can't figure out what's causing it. The point of this code is to create a structure of type credit card which is defined in the header file which has a hardcoded set of 4 records, and be able to print the current database, add a record, delete a record, and other choices from the menu. Right now I am focusing on adding and deleting a record, as they are the most difficult part of this program. Why do I keep getting seg fault errors when trying to add a record?
The header file:
#ifndef myStruct
#define myStruct
struct creditCard
{
char firstName[100];
char lastName[100];
char cardNumber[17]; //TA advised to use string since 16 digits will overflow in plain integer
char expMonth[10];
};
//function headers below
int printCreditCard(struct creditCard *);
int sizeOfDb(struct creditCard *);
int countRecords(struct creditCard *);
int deleteRecord(struct creditCard *);
int addRecord(struct creditCard *);
#endif
Here is the actual program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "myStruct.h"
int accesses = 0; //number of times database was manipulated
int count = 0; //used to count how many records there are; we always start at 4
//int size = 0; //used to tell us how big the database is
struct creditCard *ptr; //chunk of memory for each record/structure
struct creditCard *headPtr; //chunk of memory for the first records/structure
int main(void)
{
ptr = (struct creditCard *) malloc(4 * sizeof(struct creditCard));
headPtr = ptr;
memcpy(ptr->firstName,"Bob",100);
memcpy(ptr->lastName,"Marley",100);
memcpy(ptr->cardNumber,"0000000000000000",17);
memcpy(ptr->expMonth,"September", 10);
ptr++;
count = count++;
memcpy(ptr->firstName, "John", 100);
memcpy(ptr->lastName, "Adams", 100);
memcpy(ptr->cardNumber,"1111111111111111",17);
memcpy(ptr->expMonth, "October", 10);
ptr++;
count = count++;
memcpy(ptr->firstName, "Bill", 100);
memcpy(ptr->lastName, "Gates", 100);
memcpy(ptr->cardNumber,"2222222222222222",17);
memcpy(ptr->expMonth, "January", 10);
ptr++;
count = count++;
memcpy(ptr->firstName, "Steve", 100);
memcpy(ptr->lastName, "Jobs", 100);
memcpy(ptr->cardNumber,"3333333333333333",17);
memcpy(ptr->expMonth, "May", 10);
count = count++;
while (1)
{
//headPtr = ptr; //put the newest database into headPtr so it points to the first record in that database
//ptr = headPtr; //start the database back at the first record
//countRecords(ptr); //update the count of the current database
int sel;
printf("MAIN MENU\n");
printf("=====\n");
printf("1. Select 1 to print all records.\n");
printf("2. Select 2 to print number of records .\n");
printf("3. Select 3 to print size of database.\n");
printf("4. Select 4 to add record.\n");
printf("5. Select 5 to delete record.\n");
printf("6. Select 6 to print number of accesses to database.\n");
printf("7. Select 7 to Exit.\n");
printf("Enter Your Selection: \n");
scanf("%d", &sel); //get user input;
if (sel == 1)
{
printCreditCard(ptr);
accesses++;
}
else if (sel == 2)
{
fprintf(stderr,"Number of records in the database is %d records\n", count); //pulls value of count from global updated variable
accesses++;
}
else if (sel == 3)
{
sizeOfDb(ptr);
accesses++;
}
else if (sel == 4)
{
ptr = headPtr;
addRecord(ptr);
accesses++;
}
else if (sel == 5)
{
deleteRecord(ptr);
accesses++;
}
else if (sel == 6)
{
fprintf(stderr,"Number of accesses to the database is %d\n", accesses);
accesses++;
}
else if (sel == 7)
{
printf("Now Exiting.\n");
return 0;
}
else
{
printf("Invalid input, please select a valid option.\n");
break; //go back to the main menu
}
}
}
//functions defined below
int sizeOfDb(struct creditCard *card2)
{
int size = 0;
int j;
for (j = 1; j <= count; j++)
{
size += sizeof(card2->firstName); //get the size of each element
size += sizeof(card2->lastName);
size += sizeof(card2->cardNumber);
size += sizeof(card2->expMonth);
card2++;
}
//loop through each record and get sizeof() of each record
fprintf(stderr, "Total Size of the Database is %d bytes.\n", size);
return size;
}
int addRecord(struct creditCard *card3)
{
count = count++;
fprintf(stderr, "count is %d \n", count);
int p;
struct creditCard *tempStruct;
//struct creditCard *dummy;
char fName, lName, month, number;
//tempStruct = (struct creditCard *) malloc (count * sizeof(struct creditCard)); //allocate memory to a dummy record
tempStruct = (struct creditCard *) malloc ((count+1) * sizeof(struct creditCard)); //allocate memory to a dummy record
//dummy = (struct creditCard *) malloc (sizeof(struct creditCard));
//dummy = (struct creditCard *) malloc (2 * sizeof(struct creditCard));
card3 = headPtr; //start at the beginning of the old database
for (p = 1; p < count; p++) //copies the old database in the new database up to the record before the newly allocated record
{
memcpy(tempStruct->firstName, card3->firstName, 100);
memcpy(tempStruct->lastName, card3->lastName, 100);
memcpy(tempStruct->cardNumber, card3->cardNumber, 17);
memcpy(tempStruct->expMonth, card3->expMonth, 10);
fprintf(stderr, "first name is %s\n", tempStruct->firstName);
if (p == count-1)
{
tempStruct++;
}
else
{
tempStruct++;
card3++;
}
}
printf("Please enter your first name.\n");
scanf("%s", &fName);
fprintf(stderr, "fname is %s\n", &fName);
memcpy(tempStruct->firstName, &fName, 100);//put first name in struct
//memcpy(dummy->firstName, &fName,100);//put first name in struct
fprintf(stderr, "struct name is %s\n", tempStruct->firstName);
//fprintf(stderr, "dummy name is %s\n", dummy->firstName);
printf("Please enter your last name.\n");
scanf("%s", &lName);
memcpy(tempStruct->firstName, &fName, 100);//put first name in struct
//memcpy(dummy->lastName,&lName,100);//put last name in struct
printf("Please enter your 16 digit credit card number with no spaces.\n");
scanf("%s", &number);
memcpy(tempStruct->firstName, &fName, 100);//put first name in struct
//memcpy(dummy->cardNumber,&number,17);//put creditcard number in struct
printf("Please enter the month in which your credit card expires.\n");
scanf("%s", &month);
memcpy(tempStruct->firstName, &fName, 100);//put first name in struct
//memcpy(dummy->expMonth,&month, 10); //put month of expiration in struct
//code below copies stuff from the dummy record to the new database called tempStruct
//memcpy(tempStruct->firstName, dummy->firstName, 100);
//memcpy(tempStruct->lastName, dummy->lastName, 100);
//memcpy(tempStruct->cardNumber, dummy->cardNumber, 17);
//memcpy(tempStruct->expMonth, dummy->expMonth, 10);
card3 = tempStruct; //put the new database in place of the old database
//free(dummy); //clear memory for the dummy record because we don't need it anymore
return 0;
}
int deleteRecord(struct creditCard *card4) //goes to the last record in the database and clears the memory for it, essentially deleting it
{
count = count--;
int l;
struct creditCard *newDb; //will hold the new database with one less record at the end
newDb = (struct creditCard *) malloc(count * sizeof(struct creditCard));
for (l = 0; l < 4; l++)
{
memcpy(newDb->firstName,card4->firstName,100);
memcpy(newDb->lastName,card4->lastName,100);
memcpy(newDb->cardNumber,card4->cardNumber,17);
memcpy(newDb->expMonth,card4->expMonth,10);
card4++;
}
//now we need to put the data into the new record
card4 = newDb; //put the new database into ptr to hold as the new database
return 0;
}
int printCreditCard(struct creditCard *card)
{
card = headPtr; //start at the beginning of the database
int i;
if (count == 0)
{
printf("The database is empty\n");
return 0;
}
else
{
for (i = 1; i <= count; i++)
{
printf("Credit Card Record %d\n", i);
fprintf(stderr, "First Name = \%s\n", card-> firstName);
fprintf(stderr, "Last Name = \%s\n", card-> lastName);
fprintf(stderr, "Card Number = \%s\n", card-> cardNumber);
fprintf(stderr, "Expiration Date = \%s\n\n", card-> expMonth);
card++; //go to the next record to print
}
}
return 1; //we have now printed all records, go to main menu.
}
There is really a lot wrong here-- you should try using lint or another static analysis tool to help you find errors.
One particular problem -- when you input fname, you are passing scanf a pointer to a single character-- you really want to pass it a pointer to an array of characters (actually, you don't want to use scanf at all, but I won't get into that). Scanf is merrily copying the input characters into the memory positions after that single char, which of course will cause a segfault at some point.
You'll also need to learn to use some sort of debugger (gdb?) which will help you look at the core dump when you get a segfault so you can find where things went wrong.

realloc struct of array inside function

I have made a library program to store movies in and using dynamic memory allocation for my struct array without success. Adding the first record (movie) works fine, but after the second the values are just messed up characters.
There is not really much more to say than showing my code.
The problem is that I can't realloc inside my function addmovie();
But if I put this line:
movie = (struct movies *) realloc(movie, (records+1) * sizeof(struct movies));
Right before calling addmovie(); function it seems to work, why?
/* Global variables */
int records = 0; // Number of records
struct movies{
char name[40];
int id;
};
addmovie(struct movies **movie)
{
int done = 1;
char again;
int index;
while (done)
{
index = records;
records++; // Increment total of records
struct movies *tmp = (struct movies *) realloc(movie, (records+1) * sizeof(struct movies));
if (tmp)
*movie = tmp;
system("cls");
fflush(stdin);
printf("Enter name of the Movie: ");
fgets(movie[index].name, 40, stdin);
fflush(stdin);
printf("Enter itemnumber of the Movie: ");
scanf("%d", &movie[index].id);
printf("\nSuccessfully added Movie record!\n");
printf("\nDo you want to add another Movie? (Y/N) ");
do
{
again = getch();
} while ( (again != 'y') && (again != 'n') );
switch ( again )
{
case ('y'):
break;
case ('n'):
done = 0;
break;
}
} // While
}
int main()
{
int choice;
struct movies *movie;
movie = (struct movies *) malloc(sizeof(struct movies)); // Dynamic memory, 68byte which is size of struct
while (done)
{
system("cls");
fflush(stdin);
choice = menu(); //returns value from menu
switch (choice)
{
case 1:
addmovie(movie);
break;
}
} // While
free(movie); // Free allocated memory
return 0;
}
C is a pass-by-value language. When you do:
movie = (struct movies *) realloc(movie, (records+1) * sizeof(struct movies));
In your function, movie from main() isn't affected at all. You need to pass a pointer-to-a-pointer:
void addmovie(struct movies **movie)
and then modify the pointer's contents:
struct movies *tmp = realloc(...)
if (tmp)
*movies = tmp;
Note that it's also important not to assign the return value of realloc back to the variable to passed to it - you might end up leaking.
Check the comp.lang.c FAQ question 4.8 for a complete explanation.

Creating array of structure

I have been busy with a question from a C book. The question is simple but it has some specific parts.
I would like to ask a question about arrays.
My question is about the best way with creating an array of a structure. The question wants these all;
Firstly create an array of structure. Secondly, create a linked list which connects these arrays with a restp pointer.
I want to divide my question into sub parts. First part is array of structure...
How can I create an array of a structure. I've made a research about this. And here is my way:
I'm creating a structure for my array of structure:
struct student{
int id;
struct courseList_node_s *restp;
};
And my linked list for completing rest of question:
typedef struct courseList_node_s{
char course[6];
int credit,
section;
struct courseList_node_s *restp;
}courseList_node_t;
I have implemented some function to handle this student schedule.
In my get_studentList function;
I declared my array as this;
struct student *ansp[size];
And making memory allocation;
ansp[i] = malloc(sizeof(struct student));
And lastly assigning a value;
ansp[i]->id =id;
Now, my problem is while creating an array, I couldn't make it as an ordered array. For instance, the user can type 1111, 1222, 1232, and then 1011. So, my first element of array which is ansp[0] = 1011, and ansp[1] = 1111.
I couldn't figure out.
Can you give me an algorithm which consist these(Creating an ordered array of structure).
Lastly, sorry for my bad English and I may made some grammatical mistakes...
Thanks in advance.
To order the elements, you will need to sort them. In C, you probably want to use qsort (in C++ there are easier ways). You will need to define a comparison function on struct student * and call qsort on your array with it.
See this example for inspiration. Note that your array is an array of structure pointers, the example is an array of direct structures (which is maybe what you wanted anyway?).
Can you give me an algorithm which consist these(Creating an ordered array of structure).
If you want to create an orderd array of structures, you probably want to build a tree.
There are libraries for that, but to learn and understand, you can Google 'Binary trees in C' or something like that, e.g.:
http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/tree.html
Trees will allow your user to insert non-sorted values and retrieve them in sorted order (also, search them more quickly).
I'd solved the problem with helps #Keith Randall and
lserni
I have implemented both binary search tree and array of structure.
First way, sorting array with qsort:
I had to create a compare function:
int compare(const void *p1, const void *p2){
return (* (struct student **) p1)->id - (* (struct student **) p2)->id;
}
And my other helper functions;
void get_studentList(struct student **listp,int size){
int id,i;
struct student *ansp[size];
for(i=0;i<size;i++){
printf("Enter student's id to exit enter -1> ");
scanf("%d", &id);
ansp[i] = malloc(sizeof(courseList_node_t));
ansp[i]->id = id;
ansp[i]->restp = NULL;
}
qsort (ansp, size, sizeof(struct student *), compare);
for(i=0;i<size;i++){
listp[i] = ansp[i];
}
}
courseList_node_t * insert_studentSchedule(courseList_node_t *headp, int size){
courseList_node_t *cur_nodep;
if(headp == NULL){
cur_nodep = scan_course();
headp = cur_nodep;
} else {
headp->restp = insert_studentSchedule(headp->restp,size);
}
return (headp);
}
And my display function;
void display_schedule(struct student **headp, int size){
courseList_node_t *cur_nodep;
int i = 0;
while(i< size){
cur_nodep = headp[i]->restp;
printf("Student id > %d\n", headp[i]->id);
while(cur_nodep != NULL){
printf("Course name> %s\t", cur_nodep->course);
printf("Course credit> %d\t", cur_nodep->credit);
printf("Course section> %d\n", cur_nodep->section);
cur_nodep = cur_nodep->restp;
}
i++;
}
}
Second way, Binary Search Tree:
I changed typedef parts of my header file as this:
typedef struct tree_node_s{
int id;
struct courseList_node_s *restp;
struct tree_node_s *leftp, *rightp;
}tree_node_t;
And my macro to formalize a standart pattern in dynamic allocation of nodes:
#define TYPED_ALLOC(type) (type *)malloc(sizeof(type))
And my implementation of creating a binary search tree:
/*
* Insert a new id in a binary search tree.
* Pre: rootp points to the root node of a binary search tree
*/
tree_node_t * get_studentTree(tree_node_t *rootp, int newId)
{
if (rootp == NULL){
rootp = TYPED_ALLOC(tree_node_t);
rootp->id = newId;
rootp->restp = NULL;
rootp->leftp = NULL;
rootp->rightp = NULL;
} else if ( newId == rootp->id){
/* */
} else if (newId < rootp->id){
rootp->leftp = get_studentTree(rootp->leftp, newId);
} else {
rootp->rightp = get_studentTree(rootp->rightp, newId);
}
return (rootp);
}
This parts are not related with this question. I gave them because I want to share the partial solution of real question.
/*
* Its aim to add courses to restp component of subtree
* It may have some problems. And you can omit it. Because it not related with this question
* Pre: elementp not empty
*/
courseList_node_t * add_course(courseList_node_t *nextp, courseList_node_t *elementp){
if(nextp->restp == NULL){
nextp->restp = elementp;
} else {
nextp->restp = add_course(nextp->restp,elementp);
}
return (nextp);
}
/*
* It is not neccessary to first call get_studentTree function. It simply creates a linked list which consist of student class/lecture schedule.
* Pre: ele and id not empty
* Post: Tree returned includes all schedule and retains binary search tree properties.
*/
tree_node_t * insert_studentSchedule(tree_node_t *rootp,courseList_node_t *ele, int id){
if (rootp == NULL){
rootp = get_studentTree(rootp, id);
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
}
else if(rootp->id == id){
if ( rootp->restp == NULL ){
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
} else {
rootp->restp = add_course(rootp->restp, ele);
}
} else if ( id < rootp->id ){
if ( rootp->leftp != NULL )
rootp->leftp = insert_studentSchedule(rootp->leftp, ele, id);
} else if ( id > rootp->id ) {
if ( rootp->rightp != NULL )
rootp->rightp = insert_studentSchedule(rootp->rightp, ele, id);
}
return (rootp);
}
/*
* Course scanning function
*/
courseList_node_t * scan_course(void){
courseList_node_t *cur_coursep;
char courseName[6];
cur_coursep = (courseList_node_t *)malloc(sizeof(courseList_node_t));
printf("Welcome to course scanning part>\n");
printf("Enter the name of course> ");
scanf("%s", courseName);
strcpy(cur_coursep->course, courseName);
printf("Enter the credit of course> ");
scanf("%d", &cur_coursep->credit);
printf("Enter the section of course> ");
scanf("%d", &cur_coursep->section);
cur_coursep->restp = NULL;
return (cur_coursep);
}
/*
* My way to print binary search tree with all elements
*/
void display_schedule(tree_node_t *rootp){
courseList_node_t *cur_course;
if(rootp == NULL)
return;
display_schedule(rootp->leftp);
if (rootp->restp == NULL)
printf("Tree with id: %d element has no member!", rootp->id);
else {
cur_course = rootp->restp;
while (cur_course != NULL){
printf("Student Id> %d\n", rootp->id);
printf("Course name> %s\t", rootp->restp->course);
printf("Course credit> %d\t", rootp->restp->credit);
printf("Course section> %d\n", rootp->restp->section);
cur_course = cur_course->restp;
}
}
display_schedule(rootp->rightp);
}
It may not full solution of book question but with your helps, It is solution of essential parts. If you found a mistake. Feel free to add a comment.

Resources