A lecturer teaches 4 different classes.
The number of students in each class may differ from each other.
There are two different linked list structures for holding courses and students.
In the structure of the class (nodeClass), information about which class it is (classID) and the average of the midterm exams of the students in the class (classMidtermAverage) are kept. Besides these, there is a pointer pointing to the next class and a pointer pointing to a node belonging to the structure (nodeStudent) used to define students' information.
In the structure called nodeStudent, there is a student's id, midterm grade and a pointer showing the next student in the same class.
The program takes the student number and midterm grade from the user as input. Students whose student number starts with 66 are in the 1st class, with 77 in the 2nd class, students starting with 88 are in the 3rd class, and students starting with 99 are in the 4th class. Students must appear in the linked list sequentially. Sorting will be done in descending order according to the midterm grade. If the notes are the same, the lower number should be first in the list. The sorted list should be preserved by adding it to the correct location while adding. After all students are added to the list, the midterm average of each class will be calculated and kept in the classMidtermAverage variable of the node generated from the nodeClass structure of the relevant class.
I know we have to create a nested linked list but I am having a hard time inserting the data to the main linked list (being the classes linked list) and the child linked list (students list)
struct nodeClass
{
int classID;
double classMidtermAverage;
struct nodeClass *next;
struct nodeStudent *studentPtr;
};
struct nodeStudent
{
int studentID;
int midterm;
struct nodeStudent *next;
};
struct nodeClass* insert(struct nodeClass **head, int id, int midterm) {
struct nodeStudent* newPtr;
struct nodeClass* temp= (struct nodeClass*) malloc(sizeof(struct nodeClass*));
temp->studentPtr = (struct nodeStudent*) malloc(sizeof(struct nodeStudent));
temp->studentPtr->studentID=id;
temp->studentPtr->midterm=midterm;
long classcode=id;
while (classcode>=100){
classcode=classcode/10;
}
if (classcode=66) {
temp->classID=i;
head=temp;
}
else if( classcode=77) {
temp->classID=2;
head->next=temp;
struct nodeClass* class2= head->next;
}
else if( classcode=88) {
temp->classID=3;
head->next->next=temp;
struct nodeClass* class3= head->next->next;
}
else if( classcode=99) {
temp->classID=4;
head->next->next->next=temp;
struct nodeClass* class3= head->next->next->next;
}
return head;
}
struct nodeClass* computeClassAverage(*head) {
nodeClass* tmp;
for( tmp=head; tmp)
}
void printAll(*head);
and the main function is
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "function.h"
int main()
{
struct nodeClass *head = NULL;
int id, midterm;
scanf("%d", &id);
while(id!=-1)
{
scanf("%d", &midterm);
insert(&head, id, midterm);
scanf("%d", &id);
}
computeClassAverage(head);
printAll(head);
return 0;
}
You seem to have some misunderstanding of this subject matter which I can't quite see, so I doubt that this answer will satisfy you, but I'll go out on a limb.
Here is a way to insert new elements into the linked list:
nodeStudent* insertStudent(nodeStudent *head, nodeStudent *newp)
{
newp->next = head;
return newp;
}
nodeClass* insertClass(nodeClass *head, nodeClass *newp)
{
newp->next = head;
return newp;
}
Notice that these functions add the new elements at the head of the list. It is not difficult to write functions to add elements after a given element, or find the end of the list and insert the new element there.
Related
I'm trying to create a simple singly linked list. Previously, I successfully did this with no errors, however now I encounter an error. I suspect that there is some kind of problem with memory allocation because of the if statement in line 23.
What I've tried:
I used typecasting in all of my declarations even though it is not necessary in C.
I removed the if statement and I still encountered the errors.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int value;
struct Product *next;
} Product;
int main()
{
int user_choice;
Product *head;
head = malloc(sizeof(Product));
head->next = NULL;
head->value = 5;
printf("\n Do you want to add a new node (0 for no, 1 for yes)? \n");
scanf("%d", &user_choice);
if (user_choice == 1) // line 23
{
head->next = malloc(sizeof(Product));
if (!head->next)
printf("\n Memory allocation failed! \n");
head->next->next = NULL; // 1st error
printf("\n Enter a value: \n");
int value;
scanf("%d", &value);
head->next->value = value; // 2nd error
}
free(head);
free(head->next);
}
typedef struct
{
} Product;
Declares a type alias called Product for an unnamed struct - however you need a named struct for your forward declaration struct Product *next;, otherwise the compiler cannot determine which definition it belongs to.
The simplest solution is to give the struct a name:
typedef struct Product
{
int value;
struct Product *next;
} Product;
While teaching my self how to manage linked lists in C i came across some difficulties. I created a function getNode to create a list of 4 integers. Now i would like to printf the first element of the list, so that i can learn something new. Unfortunatelly, when i try to recall the head node of the list, the program prints the last node. When all code was in main() , there was no problems or what so ever, only when i got to factorize the code the dificulities mentioned have occured. It might be just lacking a pointer, or some sort of logical error. Any help apreciated! thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct list
{
int x;
struct list *next;
}list;
list *getNode()
{
int marker = 0;
int base;
list *head, *current;
head=current=NULL;
while (marker < 4)
{
printf("wprowdz liczbe dla NodE o markerze: %d \n", marker + 1);
scanf("%d", &base);
list *node = malloc(sizeof(list));
node->x = base;
node->next = NULL;
if (head == NULL)
{
current = head = node;
}
else
{
current = current->next = node;
}
marker++;
}
return current;
}
void printNode(list *head)
{
printf("this shoud print the first element of linked list :");
printf("%d", head->x);
}
int main()
{
list *start = getNode();
printNode(start);
}
My dear friend, in the function getNode you need to return the head pointer not the current pointer. The head pointer points at the first node but the current node is pointing at the last node because you are updating the current node everytime while loop is executed.
So, we need to return the head pointer in order to traverse through the linked list or print the first element. Hope you get it !! Cheers, feel free to ask questions
I have the following code and I am trying to make it more dynamic and reusable.
Well, I have a struct named Student and struct list, which contains all the added students. I have a function "int addStudent(Student b, list StudentList){", and I am trying to pass the structs Student and StudentList as parameters. But the problem is that I am doing something wrong and my list does not contains all the Students added. It contains only the last one.
Can you help me?
NOTE: I have to create a body for the "int addStudent(Student b, list StudentList)". It is not permitted to change the declaration of this function ... this is very difficult for me and I need suggestions to work on ...
thank you in advance!
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRING 100
#define MAXLessonS 100
typedef enum genders{
female,
male
} genders;
typedef struct Student
{
char name[MAXSTRING];
char Surname[MAXSTRING];
enum genders gender;
int id;
char Lessons[MAXLessonS][MAXSTRING];
} Student;
typedef struct list
{
struct list * next;
struct Student * Student;
} list;
void printlist(list * StudentList)
{
list * current = StudentList;
while (current != NULL) {
printf("Student ID = %d\n", current->Student->id);
printf("Student name = %s\n", current->Student->name);
printf("Student Surname = %s\n", current->Student->Surname);
printf("Student gender = %d\n", current->Student->gender);
printf("Student Lesson = %s\n", current->Student->Lessons);
current = current->next;
}
}
int main()
{
Student b={"name 1","Surname 1",male,22,{"Lesson 1"}};
Student c={"name 2","Surname 2",female,32,{"Lesson 2"}};
list* StudentList = NULL;
StudentList = malloc(sizeof(list));
StudentList->next = NULL;
//StudentList->next->next = NULL;
int x=addStudent(b,StudentList);
StudentList->next=NULL;
int xx=addStudent(c,StudentList);
printlist(StudentList);
return 0;
}
int addStudent(Student b, list StudentList){
//StudentList=malloc(sizeof(list));
StudentList.Student = &b;
//StudentList.next->next=NULL;
//free(StudentList);
return 1;
}
The addStudent method always overwrites previous nodes. So your list only ever contains 1 node. Also, to "store" a linked list, you would want to keep a pointer to the head (first element) of the list.
You have two problems:
1) You add the address of a local variable to the list
2) You never expand the list, i.e. it always contain a single element
To solve problem 1) change the addStudent function like:
int addStudent(Student* b, list* StudentList){
^^^ ^^^
Use a pointer
StudentList->Student = b;
^^^
Save the pointer
return 1;
}
and call it like:
int x=addStudent(&b, StudentList);
^^
To solve problem 2):
You need to malloc a new list item and insert it into the current list.
However, your current code is a bit strange as you also allocate a list in main but puts nothing into it. Instead it would seem better to only allocate list items in the addStudent function.
A simple way to do that is:
// This function inserts new item in the front of the list
list* addStudent(Student* b, list* StudentList){
list* t;
t = malloc(sizeof(list));
if (!t) exit(1);
t->next = StudentList;
t->Student = b;
return t;
}
int main()
{
Student b={"name 1","Surname 1",male,22,{"Lesson 1"}};
Student c={"name 2","Surname 2",female,32,{"Lesson 2"}};
list* StudentList = NULL;
StudentList = addStudent(&b, StudentList);
StudentList = addStudent(&c, StudentList);
printlist(StudentList);
return 0;
}
Use a while to go to the last element with a pointer, then create your new element in your list
void addStudent(Student *b, list *StudentList)
list *elem;
elem = StudentList;
while (elem->next)
elem = elem->next;
//now you can create your elem
elem->next = malloc(sizeof(list));
elem->next->student = b;
elem->next->next = NULL;
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;
}
I am trying to create an (ordered) linked list of (ordered) linked lists. The list-of-list links are carried by the first nodes of its member lists. I am trying to achieve this via the following code, but my program crashes right after I try to insert the second node into the list of lists.
Here's a schematic of the data structure I am trying to construct:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node{
int number;
struct node*next;
struct node*lsnext;
};
typedef struct node Node;
Node* insertValue(Node * list, int value);
void display(Node*);
Node* insertArr(Node * list, int value);
int main()
{
Node *globalList = NULL, *lists,*start,*save;
int nbrOfLists, listNo, nbrOfVal, valNo, val;
printf("\n Enter the number of lists:");
scanf("%d", &nbrOfLists);
if(nbrOfLists < 0)
return -1;
for(listNo = 0; listNo < nbrOfLists; listNo++)
{
printf("\n\n Enter the number of inputs to the list %d: \n ",listNo+1);
scanf("%d", &nbrOfVal);
lists = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++)
{
printf("Enter node value %d:", valNo+1);
scanf("%d", &val);
// Here we insert the value in both lists
lists= insertValue(lists, val);
globalList = insertValue(globalList, val);
}
start=lists;
if(listNo==0){
save=start;
}
start=start->lsnext;
printf("\n The list %d is: ",listNo+1);
display(lists);
}
printf("\n\n The final list is: ");
display(globalList);
printf("The first list is");
display(save);
printf("The second list is");
display(save->lsnext); // CRASHES HERE
return 0;
}
Node* insertValue(Node * list, int value)
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
{
newNode->next=NULL;
return newNode;
}
if(value < list->number)
{
newNode->next = list;
return newNode;
}
m = list;
while(m->next)
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next;
m->next = newNode;
return list;
}
void display(Node*nodex){
while(nodex)
{
printf("%d ->",nodex->number);
nodex=nodex->next;
}
}
What is causing my error?
Your insertArr() function is wrong. Even its signature is wrong. Instead of linking together the first nodes of existing lists, it creates a perpendicular list of separate nodes. Note in particular that it accepts a value where it needs instead to accept the head node of a list.
Moreover, even the circumstances under which you call that function are wrong. You seem to try to link the initial head nodes of each list, but the head node may change as you add values. You must wait until you have a full list before you know what its final head node is; only then can you link that list into your list of lists.
Edit: I had first asserted that your problem was failure to initialize the lsnext members of your nodes. That would be correct if your insertArr() function were actually accepting nodes created by insertValue() as its second argument, as it should, but it is not correct for the code presented. The actual problem is a consequence of the issue described in my first paragraph, that insertArr() creates a separate list of separate nodes. In particular, those separate nodes do not have their next pointers initialized.