Segmentation fault after value assignment to pointer in C - c

There is code:
void pop(int id, List *head) {
List **previous = head;
List **current = (*previous) -> next;
if(head -> next == NULL && (*head).id == id) {
free(head);
} //if only 1 node in List
while((**current).id != id) {
*previous = head -> next;
*current = previous;
}
(*previous) -> next = (*current) -> next;
free(*current);
}
The program falls with segmentation fault on third stroke List **current = (*previous) -> next (I checked it with printfs).
CLion debuggers says Exception: EXC_BAD_ACCESS (code=1, address=0x113d349e2)
If I do printf("address = %d\n", &((*previous) -> next)); it gives me the address.

void delete_worker_by_id(int id, List *head) {
List **previous = &head;
List *current = (*previous) -> next;
if(head -> next == NULL && (*head).id == id) {
free(head);
head = NULL;
} //if only 1 node in List
while((*current).id != id) {
*previous = current;
current = current -> next;
}
if((*current).id == id) {
(*previous) -> next = current -> next;
current -> next = NULL;
free(current);
return;
}
puts("No worker with this id");
}

Related

Can I insert a node before current node in singly linked list using C?

Is this even possible, because singly linked list does not have pointer to previous, only next? I have a task to do where I have to write a function that inserts a node before current node, and I just can't seem to do it.
EDIT: I made this
void before(List* list, int value) {
Node * temp = new_node(value);
temp->data = value;
temp->next = NULL;
if(list->size == 0){
temp->next = list->current;
list->current = temp;
return;
}else{
for(Node * p = list->head->next; p == list->current; p = p->next){
list->head = list->current;
list->current = list->current->next;
}
temp->next = list->head->next;
list->head->next = temp;
}
}
But for input
insert_after_current(list, 1);
insert_after_current(list, 2);
insert_after_current(list, 3);
insert_after_current(list, 4);
before(list, 5);
I receive output
1 5 2 3 4
Can someone explain why?
As you traverse the list, you need to keep track of the previous node you visited.
Once you find the node you want to insert before, have the previous node point to the new node and have the new node point to the current node.
typedef struct node
{
struct node *next;
}node;
node *insert(node *parent, node *newnode)
{
if(parent && newnode)
{
newnode -> next = parent -> next;
parent -> next = newnode;
}
}
node *insertbefore(node **haystack, node *needle, node *newnode)
{
node *parent = *haystack;
if(needle == *haystack)
{
newnode -> next = *haystack;
*haystack = newnode;
}
else
{
while(parent -> next)
{
if(parent -> next == newnode)
{
insert(parent, newnode);
}
else
{
newnode = NULL;
}
}
}
return newnode;
}

Can't delete a node using a condition in circular linked list in c

I have a circular linked list as follows which keeps a status of data to be processed. The status is used to decide to delete from the list which could be at the beginning, middle or end. The list might not even have any data at all at times or might have more than one node to delete.
struct data
{
bool status;
char other_info[20];
struct data *next;
};
I tried the following code
struct data* delete_nodes(struct data *head)
{
struct data* first = NULL, *prev = NULL, *temp = NULL;
first = head;
temp = head;
prev = head;
do
{
//prev = temp;
if (temp != NULL && temp->next == head)
{
head->next = NULL;
free(temp);
head = NULL;
return head;
}
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
else if(temp != NULL)
temp = temp->next;
if (temp == NULL)
return head;
} while (temp != NULL && first != temp);
head = temp;
return head;
}
Now, pushing data into it works fine. deleting also works fine if there is only one node. but when there are more than one node to be deleted it crashes.
The delete_nodes() function is invoked by a thread which processes data if there is any and invokes delete_nodes()
This code block
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
is for sure wrong when doing the first iteration.
At the first iteration prev and temp are both the same as head. So prev is pointing to the same memory as you are free-ing.
Consider to drop all the checks for NULL and only have a check in the start, i.e.
struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
// Hereafter no further checks for NULL is needed
A complete function could look like:
struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
struct data *prev = NULL;
struct data *temp = head;
struct data *first = head;
do
{
struct data *next = temp->next;
if (temp->status)
{
if (prev == NULL)
{
// Delete head element
head = temp->next;
}
else
{
// Delete middle element
prev->next = temp->next;
}
free(temp);
}
else
{
prev = temp;
}
temp = next;
} while (temp != first);
if (prev == NULL)
{
// List is empty
return NULL;
}
return head;
}
Below statement is causing the problem
prev->next = temp->next; // what is prev here ?
It should be
if (temp != NULL && temp->next !=NULL && temp->status == true) {
prev = temp;//current node which you want to delete
temp->next = prev->next;//this statement should be done before next statement..current node next should be prev node next
prev->next = temp->next;//
free(temp);
temp = prev->next;
}

Linked List output not showing correctly

I can't figure out where is the problem in my code:
typedef struct list List;
struct list {
int data;
List* next;
};
void insert_sorted(List** head, int value);
int main() {
List* head = NULL;
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
insert_sorted(&head, 3);
insert_sorted(&head, 2);
insert_sorted(&head, 40);
insert_sorted(&head, 10);
//insert_sorted(&head, 40);
List* temp = head;
while (temp != NULL) {
printf("%d\t", temp->data);
temp = temp->next;
}
printf("\n\n");
return 0;
}
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) {
node->next = *head;
*head = node;
} else {
temp = *head;
while (temp->next != NULL) {
if (temp->data < value && (temp->next)->data > value) {
node->next = temp->next;
temp->next = node;
} else
temp = temp->next;
}
temp->next = node;
}
}
1:
Run the code and see results. (Running and running...) after sorting data it is repeating some values forever.
2:
Go to
//insert_sorted(&head, 40);
this line an remove comment symbols.
Run the code and mark the result.(Time limit exceeded)
3:
Find this and remove comments:
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
Run and see results; (Again some problems)
Finally:
Remove all comments symbols and run it, this time it is working without any error but not as expected (List is not sorted correctly);
But why this is happening? Any help will be appreciated, and I am not at home at this but a learner.
Your void insert_sorted(List** head, int value) function is doing too much work.
void insert_sorted(List** head, int value) {
List* node = malloc(sizeof *node);
node->data = value;
for( ; *head ; head = &(*head)->next) {
if ((*head)->data > value) break; // we should insert before *head
}
// When we get here *head points to the pointer that needs to get node's value
// This can either be the original head (as supplied as argument tothe function)
// or some of the -> next pointers, or even the last ->next pointer.
node->next = *head;
*head = node;
}
The problem can be fixed as follows. If the node is inserted in the middle, the function can return and does not need to append the value at the end.
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) { // <-- fix
node->next = *head;
*head = node;
}
else {
temp = *head;
while (temp->next != NULL) {
if ( (temp->next)->data > value ) {
node->next = temp->next;
temp->next = node;
return; // <-- fix
}
else
temp = temp->next;
}
temp->next = node;
}
}
Your code sometimes inserted value twice (when value was not placed at the end of the list). This should fix the problem:
while(temp->next != NULL)
{
if(temp->data < value && (temp->next)->data > value)
{
node->next = temp->next;
temp->next = node;
break;
}
else
temp = temp->next;
}
if(temp->next == NULL)
temp->next = node;

Segregating even and odd nodes in a Linked List

I need to segregate even and odd nodes in a Linked List in C.
Example:
Original list: 3,1,8,2,5,6
After change: 8,2,6,3,1,5
I have a problem when the head list data is an odd number, it is cutting out the even numbers.
Example:
Original list: 3,1,8,2,5,6
After change: 3,1,5
typedef struct Node {
int data; // store information
struct Node * next; //referance to the next node
}Node;
Node * create(Node * L, int value)
{
Node *current = L ,* new_node = (Node*)malloc(sizeof(Node)); // create and allocate a node
new_node->data = value;
new_node->next = NULL;
if (L == NULL)
{
L = new_node;
current = new_node;
}
else
{
while (current->next != NULL)
current = current->next;
current->next = new_node;
current = new_node;
}
return L;
}
Node * Change_Even_Odd(Node * L)
{
Node *oddhead = NULL, *evenhead = NULL, *lastodd = NULL, *lasteven = NULL, *current = L;
while (current != NULL)
{
// if current is even node
if (current->data % 2 == 0)
{
if (evenhead == NULL)
{
evenhead = current;
lasteven = current;
}
else
{
lasteven->next = current; // to connect the node to the list in the end
lasteven = current; // final list
}
}
else
{
// if current is odd node
if (oddhead == NULL)
{
oddhead = current;
lastodd = current;
}
else
{
lastodd->next = current;
lastodd = current;
}
}
current = current->next;
}
if (evenhead != NULL) // to put the even node in the head list
L = evenhead;
if (lasteven != NULL) // link the odd nodes to the even nodes
lasteven->next = oddhead;
if (lastodd != NULL) //end of list
lastodd->next = NULL;
return L;
}
void Print_List(Node * head)
{
while (head != NULL)
{
printf("%4d", head->data);
head = head->next;
}
}
int main()
{
Node * list = NULL; //empty linked list
srand(time(NULL));
int i, size = rand() % 10 + 1;
for (i = 0; i < size; i++)
list = create(list, rand() % 10 + 1);
printf("%d\n",size);
Print_List(list);
printf("\n");
Change_Even_Odd(list);
Print_List(list);
printf("\n");
}
Change_Even_Odd(list); should be list = Change_Even_Odd(list); (I already pointed out.)
– BLUEPIXY

Reverse a linked list in c

void reverse(node *pointer) {
node *head, *curr;
head = pointer;
curr = head;
while (head != NULL) {
while (curr -> next != NULL) {
curr = curr -> next;
}
printf("%d", curr -> data);
free(curr);
curr = head;
}
}
I don't know what's wrong with the code it prints only the last node of the linked list while trying to reverse it.
Simply:
node *reverse(node *head){
node *result = NULL;
while (head) {
node *next = head->next;
head->next = result;
result = head;
head = next;
}
return result;
}
You will not be able to see the output of the above function mainly for two reasons
Passing by value instead of reference.
No print statement inside the function. The effect of this function will be destroyed as soon as it comes out of the function.
In code:
void reverse(struct node** head_ref) {
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}

Resources