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;
Related
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?
here's part of my code for the linked list:
struct node {
float data;
int key;
struct node* next;
};
typedef struct{
struct node *head;
struct node *current;
int length;
} linked_list;
linked_list *init_list(){
linked_list *out = malloc(sizeof(linked_list));
struct node *head = NULL;
struct node *current = NULL;
out->head = head;
out->current = current;
out->length = 0;
return out;
}
void push_core(struct node *head, int key, float data){
struct node *link = malloc(sizeof(struct node));
link->data = data;
link->key = key;
link->next = head;
// readjust to point at the new first node
head = link;
printf("%f; ", head->data);
}
void push(linked_list *list, int key, float data){
push_core(list->head, key, data);
list->length ++;
}
void print_list_core(struct node *head){
struct node* ptr = head;
printf("\n[");
while(ptr != NULL){
printf("(%d,%f)", ptr->key, ptr->data);
ptr = ptr->next;
}
}
void print_list(linked_list *list){
print_list_core(list->head);
}
But in the main, after I initialized the linked list structure, I wasn't able to use push() to link new pointers, why is that?
linked_list *S = init_list();
for (int i = 0; i < n; i++)
{
push(S,i,0);
print_list(S);
printf("%d;", S->length);
}
To clarify, the length of the list does update correctly. But when I try to print the list it doesn't work. Also, it's interesting that in another file when I initially just worked with the node struct and defined global variables for head and current, the code works fine. But when I try to wrap them up inside this linked_list struct, things aren't quite working as expected.
The problem occurred because you passed the pointer value of list->head to your push_code function as a parameter. This is a function call-by-value. So, when you change the head pointer inside the push_core function, it actually do not change the list->head pointer that you are expecting to. One quick fix would be returning the newly created link pointer from the push_core function and save it as list->head. The following code should fix your problem.
struct node * push_core(struct node *head, int key, float data){
struct node *link = malloc(sizeof(struct node));
link->data = data;
link->key = key;
link->next = head;
return link;
}
void push(linked_list *list, int key, float data){
list->head = push_core(list->head, key, data);
list->length ++;
}
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);
}
I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.
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);
}