Free a double linked list - c

I'm trying to free a double linked list and my question is if I also need to free all the data and pointers in every node. Thank you.
Function:
static void free_list(Room *head, Room *head2) {
Room *tmp = head;
Room *tmp2 = head2;
Room *store;
Room *store2;
tmp = head2;
tmp2 = head;
printf("\nFreeing trap list...\n");
sleep(2);
while (tmp != NULL) {
store = tmp->pNext;
free(tmp);
tmp = store;
}
printf("\nFreeing rooms list...\n");
sleep(2);
while (tmp2 != NULL) {
store2 = tmp2->pNext;
free(tmp2);
tmp2 = store2;
}
}
Structure:
typedef struct Room {
struct Room *forward;
struct Room *left;
struct Room *right;
struct Room *previous;
struct Room *pPrev;
struct Room *pNext;
Room_Type Room_Type;
bool emergency_call;
} Room;
So do I also need to free, in the example, the forward pointer and also the other types as well? head and head2 are two different pointers, each points to the start of two different lists.

This way of defining the container is very confusing:
typedef struct Room{
struct Room* forward;
struct Room* left;
struct Room* right;
struct Room* previous;
struct Room* pPrev;
struct Room* pNext;
Room_Type Room_Type;
bool emergency_call;
} Room;
Divide and conquer:
typedef struct Node {
struct Node* pPrev;
struct Node* pNext;
Room_Type Room_Type;
bool emergency_call;
} Node;
typedef struct List {
struct Node* pHead;
struct Node* pTail;
} List;
With this approach, one loop is enough:
void free_list(List *list)
{
Node *node = list->pHead;
while (node != NULL)
{
Node *next = node->pNext;
free(node);
node = next;
}
free(list);
}

Related

how to complete free string in c

typedef char *string;
struct node_t
{
struct node_t *prev;
string data;
struct node_t *next;
};
typedef struct node_t *node;
struct list_t{
struct node_t *head;
struct node_t *tail;
};
typedef struct list_t *list;
void list_destroy (list l){
node next = NULL;
if (l != NULL) {
node tmp = l->head;
while (tmp!=NULL) {
next = tmp->next;
free(tmp->data);
free(tmp);
tmp = next;
}
free(l);
}
};
I am trying to write function to free double linked list, when I am free char* type data, why it still have '\0' left? how can I free it completely?

adding to linked list generically nullptr issue

I am trying to add to a linked list generically, because i have 2 linked lists and I call the same function for the two lists.
void addToList(void* (*createNode)(void *data,char* name), int (compare)(void *a1, void *a2), void *(*getNext)(void), void(*setNext)(void *node, void* data), void *data,char* name, void **list) {
void *node = createNode(data,name);
void *head = *list;
if (head == NULL) { // if list is empty
*list = node;
}
else if (compare(head, node)) { // if first element is greater than node to add (meaning we need to add node to head of list)
setNext(node, list);
*list = node;
}
else {
// node will be inserted someplace other than head
void *current = head;
while (getNext(current) != NULL && compare(node, getNext(current))) {
// loop until we are at the end of the list OR until we have found an element greater than us
// basically, current will be the place to put the new node in
current = getNext(current);
}
setNext(node, getNext(current));
setNext(current, node);
}
Here is the struct and list and node
struct Stud {//my struct contains 2 lists
int id;
float gradeAverage;
float incomeAverage;
struct gradeList *gradelist;
struct incomeList *incomelist;
};
typedef struct Stud Students;
struct gradeNode {//the grade node with what is inside it
char courseName[20];
int grade;
struct gradeNode *next;
struct gradeNode *prev;
};
struct gradeList {//my first list with head and tail
struct gradeNode *head;
struct gradeNode *tail;
int size;
};
struct incomeNode {//my secound node
char *workplace;
float income;
struct incomeNode *next;
struct incomeNode *prev;
};
struct incomeList {//the secount list
struct incomeNode *head;
struct incomeNode *tail;
int size;
};
Here are the functions that I used
void* get_next_Income(void* head) {//used above in the generic call
return((struct incomeNode *)head)->next;
}
void* get_next_Grade(void* head) {//used above to get the income
return(((struct gradeNode *)head)->next);
}
int compareGradeNode(void *a1, void *a2) {//compares the node iam adding to the exicting node and adding accordingly
return ((struct gradeNode*)a1)->grade > ((struct gradeNode*)a2)->grade;
}
int compareIncomeNode(void *a1, void *a2) {
return ((struct incomeNode*)a1)->income>((struct incomeNode*)a2)-
>income;
}
void setNextGradeNode(void* node, void* data) {//seting the next graded
((struct gradeNode*)node)->next = data;
}
void setNextIncomeNode(void* node, void* data) {//setting the next income
((struct incomeNode*)node)->next = data;
}
Students students[30];
int numOfStuds = 0;
void* createGradeNode(void* data,char*name) {
struct gradeNode* nd=(struct GradeNode*)malloc(sizeof(struct gradeNode));
strcpy(nd->courseName, name);
assert(nd != NULL);
nd->grade = data;//setting the new node to the data the user entered!
nd->next = NULL;
return nd;//and return it
}
The problem is that I got a null ptr in the code part below.
I am using visual studio and can't solve it.
Please help.
Sorry for the long code, I am new to c.
void *head = *list;
if (head == NULL) { // if list is empty
*list = node;

How to obtain a pointer to pointer in C?

I'm supposed to write a function to remove the first node in a linked list.
List is defined like so:
struct ListNode{
int nInfo;
struct ListNode *next;
};
struct ListNode *createNode(int nInfo) {
ListNode *node;
node->nInfo = nInfo;
node->next = NULL;
return node;
}
void insertNode(struct ListNode **list, struct ListNode *node) {
//Sorting list after nInfo
struct ListNode *temp;
struct ListNode *tmpList = *list;
if(*list != NULL) { //List exists
while((tmpList->next != NULL)) {
if((tmpList->nInfo >= node->nInfo) && (tmpList->next->nInfo < node->nInfo)) {
break;
}
tmpList = tmpList->next;
}
//Found where to insert the node
temp = tmpList->next; //Saving old nextnode
tmpList->next = node; //Assigning new nextnode
node->next = temp; //Re-inserting old node
}
else{
*list = node;
}
}
The function for removing the first node looks like this:
void deleteFirst(struct ListNode **list) {
//Delete first node
struct ListNode *temppointer = *list;
if(temppointer == NULL)
return; //List is NULL
*list = temppointer->next;
}
I use the functions like so:
struct ListNode *list = createNode(100);
struct ListNode *node1 = createNode(50);
insertNode(list, node1); //Gives error, cannot convert ListNode* to ListNode**
deleteFirst(list); //Same error
I can't figure out how to obtain a pointer to the list pointer.
As we suspected, you forget to allocate memory for your nodes:
struct ListNode *createNode(int nInfo) {
ListNode *node;
node->nInfo = nInfo;
node->next = NULL;
return node;
}
Your *node is a pointer, but it still points to nothing. You must ask the heap for memory for your node:
ListNode *node = malloc(sizeof(ListNode));
Then in DeleteNode, you must return the memory to the heap, as you no longer need it:
void deleteFirst(struct ListNode **list) {
//Delete first node
struct ListNode *temppointer = *list;
if(temppointer == NULL)
return; //List is NULL
*list = temppointer->next;
free(temppointer); // release the memory.
}
Pay attention! The function you wrote for creating a node cannot work as it is: the node is allocated on the stack, in the context of the function, and it is invalid after the function has exited.
You have to allocate the memory for the node on the heap, using (p.e.) malloc. The function that remove the node from the list is responsable for its deallocation, usually using free.
[posting as an answer to get the formatting right]
Note: your insert() function is overly complex. It can be reduced to
void insertNode(struct ListNode **list, struct ListNode *node) {
for( ; *list ; list = &(*list)->next ) { //List exists
if(*(list)->nInfo >= node->nInfo) break;
}
//Found where to insert the node
node->next = *list;
*list = node;
}
#include <stdlib.h>
struct ListNode{
int nInfo;
struct ListNode *next;
};
struct ListNode *createNode(int nInfo) {
struct ListNode *node=malloc(sizeof(*node));
if(node){
node->nInfo = nInfo;
node->next = NULL;
}
return node;
}
void insertNode(struct ListNode **list, struct ListNode *node) {
// for safety
if(!list) return;
if(!node) return;
//Sorting list after nInfo
struct ListNode *temp;
struct ListNode *tmpList = *list;
if(tmpList!= NULL) { //List exists
while(tmpList->next) {
if(
((tmpList->nInfo)>= (node->nInfo))
&&
((tmpList->next->nInfo) < (node->nInfo))
) {
break;
}
tmpList = tmpList->next;
}
//Found where to insert the node
temp = tmpList->next; //Saving old nextnode
tmpList->next = node; //Assigning new nextnode
node->next = temp; //Re-inserting old node
}
else{
*list = node;
}
}
void deleteFirst(struct ListNode **plist) {
if(!plist) return;
struct ListNode *list=*plist;
if(!list) return;
*plist=list->next;
free(list);
return ;
}
void printNodes(char *title,struct ListNode *list){
printf("\n== %s\n",title);
while(list){
printf("\t%d\n",list->nInfo);
list=list->next;
}
printf("\n");
}
int main(){
struct ListNode *list = createNode(100);
struct ListNode *node1 = createNode(50);
insertNode(&list, node1);
printNodes("on start",list);
insertNode(&list, createNode(70));
printNodes("after add 70",list);
deleteFirst(&list);
printNodes("after del first",list);
}

EXC_BAD ACCESS in memcpy

I trying to build a BST and insert nodes in it. However while creating a new node I keep getting exc_bad access error.What can be the reason? Here is my code:
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
nodeKey= malloc (sizeof (bst->key_size));
nodeVal = malloc(sizeof(bst->value_size));
size_t sizeKey = sizeof(nodeKey);
memcpy(node->key, nodeKey, sizeKey); // exc_bad access
size_t sizeVal = sizeof (nodeVal);
memcpy(node->val, nodeVal, sizeVal); // exc_bad access
node->right = rightChild;
node->left = leftChild;
return node;
}
struct Node {
void *key;
struct Value *val;
struct Node *left;
struct Node *right;
};
struct BSTree {
size_t key_size, key_alignment;
size_t value_size, value_alignment;
int (*compare_func)(void *, void *);
struct Node *root;
// ... Maybe some other stuff.
};
struct Value {
char name[10];
int id;
};
Without knowing what Node, looks like, I'd say, even though you've allocated for node, you've not allocated all the members (which appear to be pointers).
Change your code to something like:
// Allocate node
struct Node *node = malloc(sizeof *node);
// Now members
node->key = malloc (sizeof (bst->key_size));
// :
If you are passing in the key and value, then do a memcpy of those values to the above locations. But hard to say without further code...
Without looking at the Node structure, I would guess what you want to do is:
if node is defined as
struct Node {
void *key;
struct Value *val;
struct Node *right;
struct Node *left;
};
then
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
node->key = malloc(bst->key_size); /* No sizeof here */
node->val = malloc(bst->value_size);
memcpy(node->key, nodeKey, bst->key_size);
memcpy(node->val, nodeVal, bst->value_size);
node->right = rightChild;
node->left = leftChild;
return node;
}
As you don't check for the returns of the mallocs (which is a design choice that can e justified), you can even write it simpler that way.
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
node->key = memcpy(malloc(bst->key_size) , nodeKey, bst->key_size);
node->val = memcpy(malloc(bst->value_size), nodeVal, bst->value_size);
node->right = rightChild;
node->left = leftChild;
return node;
}
There are people that cringe at this style but I prefer to not dilute my code too much on redundancies.

C 2D linked list

So i have
struct node {
int number;
struct node *next;
struct deck{
int number;
struct deck *next;
};
};
I want to create a 2D linked list. How can i initialize something like this?
Thanks.
Something like this maybe ?
struct deck{
int number;
struct deck *next;
}
struct node {
int number;
struct node *next;
struct deck *decks;
};
struct node *current_node, *new_node;
struct deck *current_deck, *new_deck;
current_node = (struct node *) malloc (sizeof(struct node));
for (i=0; i<number_of_nodes-1;i++) {
current_deck = (struct deck* ) malloc (sizeof(struct deck));
current_node->decks = current_deck;
for (j=0; j<number_of_decks_in_node_i-1; j++) {
new_deck = (struct deck* ) malloc (sizeof(struct deck));
current_deck->next = new_deck;
current_deck = new_deck;
}
new_node = (struct node *) malloc (sizeof(struct node));
current_node->next = new_node;
current_node = new_node;
}
First of all, you need to take deck outside node. What you have is valid C++ but not C.
You could write something like this:
struct node {
int number;
struct node *next;
};
struct deck{
struct node* nodes;
struct deck* next;
};
using cartesian system, you can. (BTW, it's not yet working for me. Trying)
struct node(){
char data[10];
node *x_link;
node *y_link;
}

Resources