Delete items from linked list causes segmentation fault - c

I have an issue where I am trying to delete an entry from a linked list but it causes a segmentation fault no matter where I try to delete the item from (head, middle, or tail). I'm not sure where the issue lies.
void
add_to_list(struct linked_list *list, int x)
{
struct node *n = malloc(sizeof *n);
n->data = x;
n->next = NULL;
if (list->head == NULL)
list->head = n;
if (list->tail != NULL)
list->tail->next = n;
list->tail = n;
}
void
remove_from_list(struct linked_list *list, int position)
{
struct node *current_node = list->head;
struct node *previous_node = NULL;
int i;
for (i = 0; i < position; i++) {
previous_node = current_node;
current_node = current_node->next;
}
if (position == 0) { // removing the head means we have to
// update the head pointer
list->head = list->head->next;
} else {
previous_node->next = current_node->next;
}
free(current_node);
if (list->tail == current_node) // remove the last element means
// updating the tail pointer
list->tail = previous_node;
}
int
main(void)
{
struct linked_list list = { .head = NULL, .tail = NULL };
add_to_list(&list, 'h');
add_to_list(&list, 'e');
add_to_list(&list, 'l');
add_to_list(&list, 'l');
add_to_list(&list, 'o');
remove_from_list(&list, 'e');
add_to_list(&list, 's');
print_list_rec(&list); // print_nodes_rec(list.head)
free_list(&list);
return 0;
}

The call
remove_from_list(&list, 'e');
specifies 'e' as a position in the list. The ascii value of 'e' is 101; you have 5 items in the list.
remove_from_list iterates through the list position times without checking whether it has reached the end.
You need to change this to either have the caller pass the index they want to remove or, better, change the second argument to be the item value to search for and modify the for loop in remove_from_list to exit when it finds this value.
void remove_from_list(struct linked_list *list, int data)
{
struct node *current_node = list->head;
struct node *previous_node = NULL;
while (current_node != NULL) {
if (current_node->data == data) {
break;
}
previous_node = current_node;
current_node = current_node->next;
}
if (previous_node == NULL) { // removing the head means we have to
In either case, it'd be safer if remove_from_list also guarded against reading beyond the end of its list

It appears that you are not checking whether you've reached the end of the list, and you might be trying to free a NULL pointer.

Related

Removing node from doubly linked list gives segmentation fault - C

I have written a program that can can add char characters to the start of a doubly linked list. Now once I have this list, the aim of my program is to remove certain char character(s) from the list entirely. For example (using curly brackets only for representative purposes): if list consists of { a, b, b, a, c }, then my program can remove all "b" from the list to make it { a, a, c}. Moreover, if my list is {b, a, c, a} or {a, c, a, b} and if I want to remove "b" then the program works fine for both cases and gives me {a, c, a}.
But there's a number of issues (for all cases assume I want to remove "b"):
if my list is {b, a, b, a, c} ("b" at front and somewhere in middle), I get segmentation fault (I think it has to do with using cursor in the while loop, but I don't know why exactly and how to fix it)
if my list is {a, b, b, a, c, b} ("b" in middle and at last) then output gives me weird symbols (I'm assuming its a memory fault, don't know why)
Here is the code I am using:
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list* next;
struct list* prev;
};
struct list* head; // global variable - pointer to head node of list.
struct list* last; // global variable - pointer to last node of list
//Creates a new list and returns pointer to it.
struct list* GetNewNode(char x)
{
struct list* newNode
= malloc(sizeof(struct list));
newNode->data = x;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
//Inserts a list at head of doubly linked list
void InsertAtHead(char x)
{
struct list* newNode = GetNewNode(x);
if(head == NULL)
{
head = newNode;
return;
}
head->prev = newNode;
newNode->next = head;
head = newNode;
struct list* temp = head;
while (temp->next != NULL) temp = temp->next;
last = temp;
}
void remove_element (char character)
{
struct list * cursor, *previous, *store_el;
//int boolean = 0;
if (head == NULL) return;
else
{
cursor = head;
while(cursor != NULL)
{
if (cursor->data == character)
{
if (cursor->prev == NULL)
{
// printf("deleting from front\n");
previous = head;
head = head->next;
head->prev = NULL;
//boolean = 1;
//free(previous);
}
if (cursor->next == NULL)
{
//printf("deleting from back\n");
previous = last;
last = last->prev;
last->next = NULL;
//boolean = 1;
//free(previous);
}
else
{
// printf("deleting from middle\n");
previous = cursor;
cursor = cursor->next;
cursor->prev = previous->prev;
store_el = previous->prev;
store_el->next = cursor;
cursor = head;
}
free(previous);
//printf("head data = %c\n", cursor->data);
}
cursor = cursor->next;
}
}
}
//Prints all the elements in linked list in forward traversal order
void Print()
{
struct list* temp = head;
printf("Forward: ");
while(temp != NULL)
{
printf("%c ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main()
{
char character;
/*Driver code to test the implementation*/
head = NULL; // empty list. set head as NULL.
// Calling an Insert and printing list before and after deletion of character
InsertAtHead('c');
InsertAtHead('a');
InsertAtHead('b');
InsertAtHead('b');
InsertAtHead('a');
Print();
printf("After deletion:\n");
remove_element ('b');
Print();
}
/*
*I changed the name of your variable 'last' to 'tail'
*I removed the code at the end of your InsertAtHead function
*I added "tail = newNode;"
*I changed the name of your variable 'previous' to 'garbage'
*I removed your variable 'store_el' completely.
*I could have changed the whole code in your remove element function because the 3 cases are unnecessary but anyway.
*/
//Inserts a list at head of doubly linked list
void InsertAtHead(char x){
struct list* newNode = GetNewNode(x);
if (head == NULL){
head = newNode;
tail = newNode;
return;
}
head->prev = newNode;
newNode->next = head;
head = newNode;
}
void remove_element (char character){
struct list * cursor, *garbage;
cursor = head;
while(cursor != NULL){
if (cursor->data == character){
garbage = cursor;
if (cursor->prev == NULL){
head = head->next;
If (head!=NULL) head->prev = NULL;
cursor=head;
}else if (cursor->next == NULL){
tail = tail->prev;
tail->next = NULL;
cursor=NULL;
}else{
garbage->prev->next = garbage->next;
garbage->next->prev = garbage->prev;
cursor=cursor->next;
}
free(garbage);
} else cursor=cursor->next;
}
}
Try it now.
The problem with your code was that you were using the memory you freed.
/*
*cursor and previous point to the same memory address
*you free the memory that the variable previous points so the cursor points to that freed memory
*when you save the next address to the cursor using that freed memory you create an undefined behaviour (your code may work or may not)
*/
cursor = head;
while(cursor != NULL)
{
if (cursor->data == character)
{
if (cursor->prev == NULL)
{
previous = head;
head = head->next;
head->prev = NULL;
free(previous);
...
cursor=cursor->next;
The Improved Code:
#include<stdio.h>
#include<stdlib.h>
//The type of your variable data was wrong. I changed it to char
struct list{
char data;
struct list *prev, *next
};
void remove_element (char character){
struct list * cursor, *garbage;
cursor = head;
while(cursor != NULL){
if (cursor->data == character){
garbage = cursor;
if (garbage->prev!=NULL ) garbage->prev->next = garbage->next;
if (garbage->next!=NULL ) garbage->next->prev = garbage->prev;
cursor=cursor->next;
if (head==garbage) head=cursor;
//Basically the tail variable has no use for your current program.
//if (tail==garbage) tail=garbage->prev;
free(garbage);
} else cursor=cursor->next;
}
}
Try to update the cursor
cursor = head;
after you delete from the front.
Ellothere I think the problem in your program is you are assigning the address of the node in previous but you are not freeing it side by side.
if (cursor->prev == NULL)
{
// printf("deleting from front\n");
previous = head;
head = head->next;
head->prev = NULL;
//boolean = 1;
//free(previous);
}
if (cursor->next == NULL)
{
//printf("deleting from back\n");
previous = last;
last = last->prev;
last->next = NULL;
//boolean = 1;
//free(previous);
}
Here you are storing node but freeing it at the end and then there are 2 if statements here then what is happening is both 'b' in {a b b a c} are next to each other so first previous variable is storing the address of first 'b' then it is storing the address of next 'b' and it is just freeing that 'b' and that one 'b' remains there . In short you should free the node side- by - side. I did this small change and it works fine .
if (cursor->prev == NULL)
{
// printf("deleting from front\n");
previous = head;
head = head->next;
head->prev = NULL;
free(previous);
//boolean = 1;
//free(previous);
}
if (cursor->next == NULL)
{
//printf("deleting from back\n");
previous = last;
last = last->prev;
last->next = NULL;
free(previous);
//boolean = 1;
//free(previous);
}
else
{
// printf("deleting from middle\n");
previous = cursor;
cursor = cursor->next;
cursor->prev = previous->prev;
store_el = previous->prev;
store_el->next = cursor;
cursor = head;
}
I have just added a free function in both if statements.

How to avoid segfault when adding to a sorted linked list?

I need to create a new function when adding a new element, it places it in the list so that the list stays in sorted order. I am not sure if my implementation is correct, my first try, with my group members, gave a segmentation fault. When I tried to do it on my own, it did not do anything. Any help will be appreciated. Here is my code:
header file:
typedef struct s{
int value;
struct s *next, *previous;
} node, *node_ptr;
c file:
#include <stdio.h>
#include <stdlib.h>
#include "double.h"
void
print_list(node_ptr list) {
// walk the list to print out the contents
while (list) {
printf("%d ",list->value);
list = list->next;
}
printf("\n");
}
void delete_list(node_ptr list) {
// walk the list to delete the elements
node_ptr t;
while (list) {
t = list;
list = list->next;
free(t);
}
}
node_ptr new_node(int value) {
node_ptr t = (node_ptr)malloc(sizeof(node));
t->value = value;
t->next = t->previous = NULL;
return t;
}
node_ptr add_to_back(node_ptr list, int value) {
node_ptr t = list;
node_ptr s = new_node(value);
// special case: starting with an empty list
if (t == NULL) return s;
// at this point we know there is a least one element in
// the list
while (t->next != NULL) // walk the list looking for the last element
t = t->next;
// we are at the end so now we arrange the pointers
t->next = s;
s->previous = t;
return list;
}
// my implementation after some research
node_ptr add_sorted(node_ptr list, int value) {
node_ptr temp = list;
node_ptr newNode;
if(temp == NULL || temp->value < newNode->value)
{
newNode->next = temp;
temp = newNode;
}
else
{
while(temp != NULL && temp->value < value)
{
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
return newNode;
}
// second implementation with team
/*
node_ptr add_sorted2(node_ptr list, int value) {
// This is the function you need to implement
// when adding a new element place it in the list so that the list stays in sorted order.
node_ptr temp = list;
node_ptr n = new_node(value);
if(temp == NULL)
{
temp->value = value;
temp->next = NULL;
return n;
}
else if(temp->next != NULL) {
while(temp->next != NULL) {
if(temp->value <= value) {
n->next = temp->next;
temp->next = n;
return n;
}
else if(temp->value > value) {
temp = temp->next;
}
else {
temp->next = n;
return n;
}
}
}
return n;
}
*/
int
main() {
int in_val;
node_ptr my_list = NULL;
node_ptr sorted_list = NULL;
scanf("%d",&in_val);
while (in_val > 0) { // going to read input until see 0 or negative
my_list = add_to_back(my_list,in_val);
sorted_list = add_sorted(sorted_list,in_val);
scanf("%d",&in_val);
}
printf("List:\n");
print_list(my_list);
printf("Sorted List:\n");
print_list(sorted_list);
delete_list(my_list);
delete_list(sorted_list);
}
The segmentation fault is clear to me, you are using an uninitialized pointer here
if(temp == NULL || temp->value < newNode->value)
// ^
Or ANY OTHER newNode's dereference anywhere, because newNode is never initialized in your code.
If temp == NULL, and you didn't initialize newNode yet then undefined behavior.
Adding a node to a list while preserving order is easy,
Create the new node
If succeeded creating it, traverse the list until the next node is greater|smaller (depending on the ordering that you desire) than the new node.
When you find it, link current's node next to the new node and the next node should be new node's next.
And that is all.

Why position 0 in delete node does not work?

Im new to c programming. I wanted to create a linked list from a given file and then randomly get a node from linked list then delete that node.
So the code works great but for the position 0 in linked list does not work.
Please help me
here's the code:
typedef struct node{
int *name;
struct node *next;
}node;
delete node:
void deleteNode(node **head_ref, int position){
if(*head_ref == NULL){
return;
}
node * temp = *head_ref;
if(position == 0)
{
*head_ref = (*head_ref)->next;
return;
}
int h;
for(h=0 ; temp!=NULL && h<position-1 ; h++){
temp = temp->next;
}
if(temp == NULL || temp->next == NULL)
return;
node * next = temp->next->next;
free(temp->next);
temp->next = next;}
getting random node:
void RandomFromList(node *head){
// IF list is empty
if (head == NULL){
return -1;
}
word = head->name;
// Iterate from the (k+1)th element to nth element
node *current = head;
int n;
for (n=2; current!=NULL; n++)
{
// change result with probability 1/n
if (rand() % n == 0)
word = current->name;
// Move to next node
current = current->next;
}
sprintf(words , "%s" , word);
deleteNode(&head , search(head , word));
printf("Randomly selected key is %s\n", words);}
and the file Reader:
node* fileReader(FILE *file){
node *t = malloc(sizeof(node));
char TopicName[20];
int fileRead = fscanf(file,"%s",TopicName);
if(fileRead != EOF){
t->name = strdup(TopicName);
tedad++;
t->next = fileReader(file);
}
if(fileRead == EOF) {
return NULL;
}
return t;}
EDIT:
When the code run's and when the position randomly got 0 the 0 position of linked list doesn't delete and continues with that node in linked list.
EDIT2:I changed my delete node and it works well without any problem, thank you guys!
node* deleteNode(node* head, unsigned i){
node* next;
if(head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next)
: (head->next = delete_at_index(next, i - 1), head);
}
The major logical problem I see with your delete function is that it is void, i.e. it returns nothing. This is fine if the node being deleted is in the middle (or end) of the list, because the head does not change. But for the case of deleting the head, the caller might expect that his reference would then point to the next node (or null, if a list of one element) after making the call. Consider this code:
node* deleteNode (node *head_ref, int position)
{
// passing in a NULL list returns NULL
if (head_ref == NULL) {
{
return NULL;
}
// deleting the first element returns the second element as the new head
node* temp = head_ref;
if (position == 0)
{
node* ret = temp->next;
free(head_ref);
return ret;
}
// otherwise walk down the list to one before the deletion position
for (int h=0; temp != NULL && h < position-1; h++) {
temp = temp->next;
}
// if found, delete the node at the desired position
if (temp != NULL && temp->next == NULL) {
node* next = temp->next->next;
free(temp->next);
temp->next = next;
}
// for cases other than deleting the head, just return the current
// (unmodified) head
return head_ref;
}
This isn't related to your problem, but don't forget to free the memory:
node * temp = *head_ref;
if(position == 0)
{
*head_ref = temp->next;
free(temp); // <--------
return;
}
Also, you already have a pointer (temp) to *head_ref, it looks cleaner to me to just use that pointer instead of dereferencing head_ref again.
void deleteNode(node **head_ref, int pos){
node *del;
for ( ; *head_ref; head_ref = &(*head_ref)->next) {
if (pos-- <= 0) break;
}
if (!*head_ref) return; // Reached end of list: nothing found
del = *head_ref;
*head_ref = del->next;
free(del);
return;
}
If you want to keep deleteNode void, then the problem is with your RandomFromList function. You are just changing the * head that exists in the function body not the pointer you passed to the function, so it's still pointing to the previous node.
It's because that pointers are passed by value (copied) like other things in C.
Try making RandomFromList return the head pointer.
P.s. I think you also have some memory leaks in the delete function.

C double linked list insertion sort memory fault

I wanted to implement insertion sort on dl_list containing char* values but I got a segmentation fault after running program (no warnings, I use gcc).
This is my structure:
struct node;
typedef struct node {
char *name;
char *surname;
char *birth_date;
char *email;
char *phone;
char *address;
struct node *next;
struct node *prev;
} node;
//doubly linked_list
typedef struct dl_list {
node *head;
node *tail;
} dl_list;
I sort it by surname, later name. When values are same it return 0, if alpha should be before beta it return -1, otherwise 1:
int compare(node *alpha, node *beta) {
int a_surn_len = strlen(alpha->surname);
int b_surn_len = strlen(beta->surname);
for (int i = 0; i < ((a_surn_len > b_surn_len) ? b_surn_len : a_surn_len); i += 1) {
if (alpha->surname[i] > beta->surname[i]) return 1;
if (alpha->surname[i] < beta->surname[i]) return -1;
//if (alpha->surname[i] == beta->surname[i]) continue;
}
if (a_surn_len != b_surn_len) return a_surn_len > b_surn_len ? 1 : -1;
int a_n_len = strlen(alpha->name);
int b_n_len = strlen(beta->name);
for (int j = 0; j < ((a_n_len > b_n_len) ? b_n_len : a_n_len); j += 1) {
if (alpha->name[j] > beta->name[j]) return 1;
if (alpha->name[j] < beta->name[j]) return -1;
//if (alpha->surname[i] == beta->surname[i]) continue;
}
if (a_n_len != b_n_len) return a_n_len > b_n_len ? 1 : -1;
return 0;
}
And here insertion algorithm on my list:
dl_list *list_sort(dl_list *list) {
// zero or one element in list
if (list->head == NULL || list->tail == NULL)
return list;
// new_head is the first element of resulting sorted list
node *new_head = NULL;
while (list->head != NULL) {
node *current = list->head;
list->head = list->head->next;
// insert the first element into an empty sorted list
if (new_head == NULL) {
current->next = new_head;
new_head = current;
new_head->prev = NULL;
// or as the head of the sorted list
} else
if (compare(current, new_head) == -1) {
current->next = new_head;
new_head->prev = current;
new_head = current;
new_head->prev = NULL;
} else {
// insert current element into proper position in non-empty sorted list
node *ptr = new_head;
while (ptr != NULL) {
// middle of the list
if (compare(current, ptr->next) == -1) {
current->next = ptr->next;
ptr->next->prev = current;
ptr->next = current;
current->prev = ptr;
break; //done
// last element of the sorted list
} else
if (ptr->next == NULL) {
current->next = ptr->next;
ptr->next = current;
current->prev = ptr;
break;//done
}
ptr = ptr->next;
}
}
}
list->head = new_head;
node *ptr2;
for (ptr2 = list->head; ptr2->next != NULL; ptr2 = ptr2->next);
list->tail = ptr2;
return list;
}
I tried to check this code on paper and it seems to work fine, on some 4-5 elements lists.
The problem is in the insertion loop: you must check if ptr->next is not NULL before comparing current with node ptr->next:
// insert current element into proper position in non-empty sorted list
node *ptr = new_head;
while (ptr != NULL) {
if (ptr->next == NULL) {
current->next = ptr->next;
ptr->next = current;
current->prev = ptr;
break;
} else
if (compare(current, ptr->next) < 0) {
current->next = ptr->next;
ptr->next->prev = current;
ptr->next = current;
current->prev = ptr;
break;
}
ptr = ptr->next;
}
You could also simplify the comparison function with strcmp():
int compare(const node *alpha, const node *beta) {
int res;
if ((res = strcmp(alpha->surname, beta->surname)) != 0)
return res;
if ((res = strcmp(alpha->name, beta->name)) != 0)
return res;
return 0;
}
And you should just compare the return value with 0 instead of explicitly with -1 or 1.
Here is a simplified version:
dl_list *list_sort(dl_list *list) {
// zero or one element in list
if (list->head == NULL || list->tail == NULL)
return list;
// new_head is the first element of resulting sorted list
node *new_head = NULL;
while (list->head != NULL) {
node *current = list->head;
list->head = list->head->next;
if (new_head == NULL) {
// insert the first element into an empty sorted list
current->prev = current->next = NULL;
new_head = current;
} else
if (compare(current, new_head) < 0) {
// or as the head of the sorted list
current->next = new_head;
current->prev = NULL;
new_head->prev = current;
new_head = current;
} else {
// insert current element into proper position in non-empty sorted list
node *ptr = new_head;
while (ptr != NULL) {
if (ptr->next == NULL) {
current->next = NULL;
ptr->next = current;
current->prev = ptr;
break;
} else
if (compare(current, ptr->next) < 0) {
current->next = ptr->next;
ptr->next->prev = current;
ptr->next = current;
current->prev = ptr;
break;
}
ptr = ptr->next;
}
}
}
list->head = new_head;
node *ptr2;
for (ptr2 = list->head; ptr2->next != NULL; ptr2 = ptr2->next)
continue;
list->tail = ptr2;
return list;
}
Your code is quite long and it will be hard to debug without a minimal example. Maybe , you can compile with the -g flag and use valgrind. That tool will give you the line of the memory fault :)
Just use: valgrind --track-origins=yes ./executable
Your problem is that your insertion loop doesn't really make sense:
node *new_head=NULL;
while(list->head != NULL){
node *current=list->head;
list->head=list->head->next;
// insert the first element into an empty sorted list
if(new_head == NULL){
current->next=new_head;
new_head=current;
new_head->prev=NULL;
1) You set new_head to be a pointer to NULL
2) You take keep a reference of head in current and make head=head->next
3) On your first loop new_head is still NULL, so you enter the if statement and set current->next=new_head. But new_head points to NULL, so this causes problems!
4) Now when you set new_head=current, current/new_head's next pointer points to NULL.
5) Finally you set new_head->prev to NULL, meaning that now current/new_head point to NULL in both directions, but your loop is waiting for list->head to be NULL! This never happens, so once you've done an iteration and try to move forward you end up in your else block
} else{
// insert current element into proper position in non-empty sorted list
node *ptr=new_head;
while(ptr != NULL){
// middle of the list
if(compare(current, ptr->next) == -1){
current->next=ptr->next;
ptr->next->prev=current;
ptr->next=current;
current->prev=ptr;
break; //done
// last element of the sorted list
} else if(ptr->next == NULL ){
current->next=ptr->next;
ptr->next=current;
current->prev=ptr;
break;//done
}
ptr=ptr->next;
}
}
6) This block tries to compare current to new_head->next. But new_head->next is NULL!

Inserting in Binary Search Tree (C) using for loop

I'm having trouble inserting in a Binary Search Tree using for loop, when I call the InorderTraversal function, there is no output all I get is a blank line, as far as I think rest of the code is okay the only problem is in the insert function.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct BinaryTree{
int data;
struct BinaryTree *left;
struct BinaryTree *right;
} node;
node* Insert(node* head, int value)
{
_Bool flag = true;
for(node *temp = head; flag == true; (temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = (node*)malloc(sizeof(node*));
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false;
}
}
return head;
}
void InorderTraversal(node* head)
{
if(head == NULL)
{
return;
}
InorderTraversal(head->left);
printf("%d ",head->data);
InorderTraversal(head->right);
}
int main(void)
{
node *head = NULL;
for(int i = 0; i < 40; i++)
{
head = Insert(head,i);
}
InorderTraversal(head);
return 0;
}
Here try these changes in your Insert function
node* Insert(node *head, int value)
{
if(!head) //Explicitly insert into head if it is NULL
{
head = malloc(sizeof *head);
head->data = value;
head->left = NULL;
head->right = NULL;
return head;
}
for(node *temp = head,*temp2 = head; ;(temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = malloc(sizeof *temp);
temp->data = value;
temp->left = NULL;
temp->right = NULL;
if(value >= temp2->data) //update previous nodes left or right pointer accordingly
temp2->right = temp;
else
temp2->left = temp;
break;
}
temp2 = temp; //Use a another pointer to store previous value of node
}
return head;
}
Call me crazy, but shouldn't that malloc(sizeof(node*)) be malloc(sizeof node)?
I am not that so informed, other than being able to read C, so excuse me if this is simply wrong...
Edit: ... or malloc(sizeof * temp)
When you insert the first node you dereference an uninitialized pointer here:
temp->data
Where temp is head and head in uninitialized and pointing to NULL.
So you first have to make special case when head is NULL:
if( !head )
{
head = malloc(sizeof(node));
head->data = value;
head->left = NULL;
head->right = NULL;
return head ;
}
When you continue adding elements you don't update the pointer of the last node. Your for loop should have an extra pointer to the previous node and when you get to the last node and find NULL update the previous nodes left or right pointer.
if(temp == NULL) //wrong, should be: not equal
{
temp = (node*)malloc(sizeof(node*)); //wrong, should be: sizeof the node not the pointer
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false; //use break instead
}
here the previous node pointer left or right is not updated and when you search you can't find any node.

Resources