Linked List not accepting values
Problem Description:
I need to make a calendar planner with a linked list in C. Im inserting a couple of Elements, and I want to insert them in a sorted order. If I try to print the List, It doesn’t show any output for the description of the appointment.
Code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
// Appointment
typedef struct
{
time_t start;
char *description;
} Appointment;
// List element
typedef struct Element
{
Appointment *appointment;
struct Element *next;
} Element;
// List of appointments
typedef struct
{
Element *head, *tail;
} List;
void printAppointment(Appointment *appointment)
{
/*
Print the Appointment structure
*/
char *description = appointment->description;
time_t startTime = appointment->start;
printf("Appointment(%s, %ld)n", description, startTime);
}
Appointment createAppointment(char *description, time_t start)
{
Appointment appointment = {0};
appointment.description = description;
appointment.start = start;
return appointment;
}
List createList()
/*
Create a linked list with a head and a tail element
*/
{
Element *head;
Element *tail;
head = malloc(sizeof(Element));
tail = malloc(sizeof(Element));
head->next = tail;
List *list;
list = malloc(sizeof(List));
list->head = head;
list->tail = tail;
return *list;
}
void clearList(List list)
/*
Free the list from all memory allocated, but keep the head and the tail
*/
{
Element *temp;
// Free elements as long as the head is not pointing to the tail
while (list.head->next != list.tail)
{
// Extract the element after the head into temp, point head at the element after
temp = list.head->next;
list.head->next = temp->next;
// Free the exctracted element
free(temp);
}
}
void debugList(List list)
/*
Print the list to the console
*/
{
struct Element *current = list.head->next;
while (current->appointment != NULL)
{
printf("%s ", current->appointment->description);
current = current->next;
}
printf("n");
}
void insertElement(List list, char *description, time_t start)
/*
Insert a new element into the list based on its value
*/
{
printf("Inserting element %s with start time %ldn", description, start);
Element *new_element = malloc(sizeof(struct Element));
Appointment new_appointment = createAppointment(description, start);
new_element->appointment = &new_appointment;
new_element->next = NULL;
if (list.head->next == list.tail)
{
// List is empty, insert new element after the head
printf("Head is pointing to tail, inserting %s in the middlen", description);
new_element->next = list.tail;
list.head->next = new_element;
return;
}
else
{
// Find the correct position for the new node in the list
struct Element *current = list.head->next;
struct Element *prev = list.head;
int index = 0;
while (1)
{
// If the new value is bigger than the current value, insert it before the current element
if (current->appointment->start >= start)
{
printf("Inserting element %s at position %dn", description, index);
prev->next = new_element;
new_element->next = current;
return;
}
// Iterate forwards
prev = current;
current = current->next;
index++;
// If the new element is bigger than all elements, insert it at the end
if (current == list.tail)
{
prev->next = new_element;
new_element->next = list.tail;
return;
}
}
}
}
Element *findElement(List list, char *description)
{
/*
Find a element in the list based on its value. Returns nullptr if the element is not found.
*/
Element *current = list.head->next;
while (current->next != list.tail)
{
Appointment currentAppointment = *current->appointment;
printf("Appointment(%s, %ld)n", currentAppointment.description, currentAppointment.start);
return NULL;
}
printf("Returning NULL, no element found!");
return NULL;
}
_Bool deleteElement(List list, char *description)
{
/*
Find a element in the list based on its value and delete it. Returns true if the element has been deleted.
*/
Element *current = list.head->next;
Element *prev = list.head;
while (current->next != list.tail)
{
char *currentDescription = current->appointment->description;
if (*currentDescription == *description)
{
prev->next = current->next;
free(current);
return true;
}
prev = current;
current = current->next;
}
return false;
}
int main()
{
// Create the list
List list = createList();
// Insert some nodes
insertElement(list, "test1", time(NULL) - 1000);
insertElement(list, "test3", time(NULL) - 3000);
insertElement(list, "test2", time(NULL) - 2000);
insertElement(list, "test4", time(NULL) - 4000);
insertElement(list, "test8", time(NULL) - 8000);
// Print the list
debugList(list);
return 0;
// Search the element with value 3
Element *el = malloc(sizeof(Element));
el = findElement(list, "test3");
//printAppointment(el->appointment);
//printAppointment(el->next->appointment);
// Delete the element with value 3
deleteElement(list, "test3");
debugList(list);
// clear the list
clearList(list);
// print the list again;
debugList(list);
return 0;
}
I can’t change any of the structs since those are a given requirement. Im fairly new to C so I dont really know why this is happening and I have absolutely no Idea on how to fix this.
The program has been compiled with gcc -g -Wall -pedantic-errors main.c
Solution – 1
You should pass a pointer to a list when you insert elements. Right now you’re passing a copy, to which you add an element, but this is not applied to your variable but to a copy of your variable. Change your function signature to:
void insertElement(List* list, char *description, time_t start)
and change all code inside the function accordingly to deal with a pointer instead of a value. Your main will look like this:
int main()
{
// Create the list
List list = createList();
// Insert some nodes
insertElement(&list, "test1", time(NULL) - 1000);
insertElement(&list, "test3", time(NULL) - 3000);
insertElement(&list, "test2", time(NULL) - 2000);
insertElement(&list, "test4", time(NULL) - 4000);
insertElement(&list, "test8", time(NULL) - 8000);
// Print the list
debugList(list);
return 0;
}
and the insertElement
function:
void insertElement(List* list, char *description, time_t start)
/*
Insert a new element into the list based on its value
*/
{
printf("Inserting element %s with start time %ldn", description, start);
Element *new_element = malloc(sizeof(struct Element));
Appointment new_appointment = createAppointment(description, start);
new_element->appointment = &new_appointment;
new_element->next = NULL;
if (list->head->next == list->tail)
{
// List is empty, insert new element after the head
printf("Head is pointing to tail, inserting %s in the middlen", description);
new_element->next = list->tail;
list->head->next = new_element;
return;
}
else
{
// Find the correct position for the new node in the list
struct Element *current = list->head->next;
struct Element *prev = list->head;
int index = 0;
while (1)
{
// If the new value is bigger than the current value, insert it before the current element
if (current->appointment->start >= start)
{
printf("Inserting element %s at position %dn", description, index);
prev->next = new_element;
new_element->next = current;
return;
}
// Iterate forwards
prev = current;
current = current->next;
index++;
// If the new element is bigger than all elements, insert it at the end
if (current == list->tail)
{
prev->next = new_element;
new_element->next = list->tail;
return;
}
}
}
}
PS There are more functions in your code where you should pass a pointer to a list instead of a copy.
Not recommended but for completion:
Another solution is to return your list everytime you insert an element, but this will be slower and you have to reassign your list everytime you insert a new element, so NOT recommended but here is the function signature anyway:
List insertElement(List list, char *description, time_t start)