Linking Linked Lists in c - c

I have 3 structures:
struct Product{
int IdOfProduct;
char *NameOfProduct;
char *CategoryOfProduct;
int PriceOfProduct;
Struct Product *NextPtr;
};
struct Customer{
int IdOfCustomer;
char *NameOfCustomer;
char *SurnameOfCustomer;
struct Baskets *ListOfBasket;
struct Customer *NextPtr;
}
*Header=NULL;
struct Basket{
int IdOfBasket;
struct Product *ProductList;
int AmountOfTotal;
struct Basket *NextPtr;
};
I took informations about customer from the user. I have customer's id name and surname. Now, the user can select one of the customers: The user enter the id of a customer that I listed by display function.So that, new basket will be added to that specific customer. How can i write this function ?

If you want to display the list of customers, I believe this is it:
void displayFunction(struct Customer *P)
{
while(P->next != NULL)
{
printf("%d %s %s",P->IdOfCustomer,P->NameOfCustomer,P->SurnameOfCustomer);
P = P->next;
}
}

Related

Build a struct with a struct inside

typedef struct Course {
char *CourseID;
char *CourseName;
struct Course* next;
} COURSE;
typedef struct Student{
int ID;
struct Student* next
}STUDENT;
I want to build a list of courses and then a list of students with the following
each student has an ID and some courses from the courses list and a grade of each course.
but how can I make that declaration inside the STUDENT struct? I cant understand that
For example
Student: 3049583222
Course: Biology (from course list)
grade: 30
and so on, every student could have all courses from the list.
My idea:
Linked List of Students.
Every student has a linked list of its courses with the grade.
The linked list elements have a pointer to the detailed course description.
// Description of a course
typedef struct Course {
char *CourseID;
char *CourseName;
} COURSE;
// Struct to hold the students grade, as a linked list to generate a list of all courses the student has.
typedef struct coursesTaken {
int grade;
COURSE* courseDescription;
struct coursesTaken* nextCourse;
} COURSES_TAKEN;
// The student with ID and pointer to his first course.
typedef struct Student{
int ID;
COURSES_TAKEN* firstCourse;
struct Student* next;
}STUDENT;
There can be multiple ways to do that, below shown are two approaches.
You can pick one and build on it.
typedef struct Course {
char *CourseID;
char *CourseName;
struct Course* next;
} COURSE;
typedef struct Student{
int ID;
}STUDENT;
//approach 1
#define NIDS 10
#define NCOURSES 20
typedef struct Student_Course_1{
STUDENT STU_ID[NIDS]; /* to store list of student ids */
COURSE STU_Courses[NCOURSES]; /* to store list of courses */
}COURSES_OF_STUDENT_1;
//approach 2
typedef struct Student_Course_2{
STUDENT STU_ID;
COURSE STU_Courses;
}COURSES_OF_STUDENT_2;
int main()
{
COURSES_OF_STUDENT_1 cs1; /* this has list of students and courses inside it */
COURSES_OF_STUDENT_2 cs2[NIDS]; /* you can use NIDS list of students and courses info with this */
return 0;
}

Doubly Lists In C

I want to find the 5 cheapest products from all shops with O(n+m) (n=node length of each shop, m=products that are available). I have figured out the algorithm in my head but I can't translate into C. I will post the header file with the structs. Here's what I want to do:
For each shop, sort its products by their price and then create another product list with the 5 cheapest products of each shop and then sort() all of them and print the first 5.
struct Shop {
int sid;
int type;
struct Product *products;
struct Shop *next;
struct Shop *prev;
};
struct Product {
int pid;
int quantity;
int price;
struct Product *next;
};
/* Global, pointer to the header node of the circular, double-linked list of shops */
struct Shop *H;
/* Global, array of pointers for the use in event 'Find Cheapest Products' */
struct Product *CheapestProducts[5];
EDIT: it just adds the products to newProd (like TMP list)
and prints the products, quantity and price for each shop . its sorted by price.
struct Shop *shop=H;
struct Product *prod;
struct Product *newProd;
int count=0;;
if(shop==NULL) return 0;
while(shop->next!=NULL)
{
prod=shop->products;
//newProd=prod;
sortPrice(prod);
while(prod!=NULL)
{
newProd=prod;
printf("<%d:%d:%d>\t" ,newProd->pid,newProd->quantity,newProd->price);
//newProd=prod;
newProd=newProd->next;
prod=prod->next;
//sortPrice(newProd);
//sortPrice(newProd);
// printf("<%d:%d:%d>\t" ,newProd->pid,newProd->quantity,newProd->price);
}
printf("\n");
//printf("<%d:%d:%d>\t" ,newProd->pid,newProd->quantity,newProd->price);
shop=shop->next;
}

Printing all "members" of a struct

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;
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!

Pointer to pointer to nested structure

There are two structures for BST
typedef struct _price {
double price;
char* shopname;
} pricing;
typedef struct _bstnode {
int id;
pricing** pl;
int nr_of_prices;
struct _bstnode *left;
struct _bstnode *right;
struct _bstnode *parent;
} bstnode;
I need to make a function that can add and update price and shop name in BST Node. One Node may contain many shops and prices
void updatePrice(bstnode* root, int id, char* shop, double price){
//to do
}
I can add a single shop name and price but how to add several objects?
(*(root->pl))=malloc(sizeof (pricing)); // ---??
(*(root->pl))->price=price;
(*(root->pl))->shopname=shop;
If nr_of_prices belongs to pl, this will add dynamically one object:
int oldidx = root->nr_of_prices++;
root->pl = realloc( root->pl, root->nr_of_prices * sizeof(*root->pl));
root->pl[oldidx] = malloc(sizeof(pricing));
root->pl[oldidx]->price = price;
root->pl[oldidx]->shopname = shop;

How to free linked list which is within another linked list?

I have a School struct that holds a linked list of Student structs and each of those Student structs hold a linked list of Courses structs. I am a bit puzzled about how I would be able to free both linked lists. I am particularly unsure about how I would free the Courses linked list since it is within another linked list.
struct Courses {
char *courseName;
int creditValue;
Courses *next;
} Courses;
struct Student {
char *studentName;
int studentAge;
Courses *coursesList; //First course (node)
Student *next;
} Student;
struct School {
char *schoolName;
int schoolAge;
Student *studentList; //First student (node)
} School;
If someone could show me an example on how I would be able to free both the linked lists that would be great!
You should think in terms of ownership: when you free an item, you must free everything it owns, that is everything his has a pointer to that is not owned by something else.
Along these lines, each list item owns the next item, every School owns its list of Students, every Student owns its list of Courses.
Your type definitions seem incorrect as you use the same identifier for types and variables. You should rewrite them this way:
typedef struct Course Course;
typedef struct Student Student;
typedef struct School School;
struct Course {
char *courseName;
int creditValue;
Course *next;
};
struct Student {
char *studentName;
int studentAge;
Course *courseList; //First course (node)
Student *next;
};
struct School {
char *schoolName;
int schoolAge;
Student *studentList; //First course (node)
};
The function to free everything:
void freeSchool(School *school) {
Student *student = school->studentList;
while (student) {
Course *course = student->courseList;
while (course) {
free(course->courseName); // if it was allocated
Course *nextCourse = course->next;
free(course);
course = nextCourse;
}
free(student->studentName); // if it was allocated
Student *nextStudent = student->next;
free(student);
student = nextStudent;
}
free(school->schoolName); // if it was allocated
free(school);
}
Note the similarity between the different levels. You can also split this function into separate freeSchool, freeStudent and freeCourse functions that you can use to handle individual object deletion in the program.
An elegant way to handle element deletion is for the freeXXX function to return the next element and free the node:
Courses *freeCourse(Course *course) {
Course *next = course->next;
free(course->courseName); // if it was allocated
free(course);
return next;
}
Student *freeStudent(Student* student) {
Student *next = student->next;
while (student->courseList) {
student->courseList = freeCourse(student->courseList);
}
free(student->studentName); // if it was allocated
free(student);
return next;
}
School *freeSchool(School *school) {
while (school->studentList) {
school->studentList = freeStudent(school->studentList);
}
free(school->schoolName); // if it was allocated
free(school);
return NULL;
}

Resources