Segmentation Fault In Linked List Append - c

I have been using linked list and I have used the following code for append function which i wrote in a new file and it works perfectly but when I copy it my main code it gives segmentation fault at while(current->next != null) . It does not give any warning while compiling so I don't know whats the issue here.
// Linked List Node for Reading Comments
struct Node{
char value;
struct Node *next;
};
void append(struct Node * headNode, char newElement){
struct Node *newNode = malloc(sizeof(struct Node)); //Dynamically Allocating Memory for New Node
struct Node *current = headNode; //Creating A Node to traverse the linked list
newNode->value = newElement; //Assigning the values of newNode to the given value
newNode->next = NULL; //Setting next value to be null since its the last node
if (headNode == NULL){ //Checking if headnode is empty
headNode = newNode; //Assigning headnode and tailnode to be newnode
}
else {
while(current->next != NULL){ //Traversing through the linked list
current = current->next;
}
current->next = newNode; //Setting tailnode's next to be newnode
}
}
void printLinkedList(struct Node* headNode){
while(headNode != NULL){
fprintf(stderr,"%c",headNode->value);
headNode = headNode->next;
}
}
If anyone can comment on this please do.

Your code does not allow to add a node to an empty list. If you try and did not initialise your head pointer on the calling side, you may get such behavior.
For instance, in main you could have:
struct Node* head; // not initialised
append(head, 'a');
printLinkedList(head);
These are then the issues:
If head happens to be not NULL, then the else block will kick in and the current pointer will reference some unintended memory address.
append will not change the head variable of main. It will only modify a local variable that happens to have a similar name (headNode).
To correct, pass the address of head to the append function, and let append deal with this accordingly:
void append(struct Node ** headNode, char newElement) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *current = *headNode;
newNode->value = newElement;
newNode->next = NULL;
if (*headNode == NULL) {
*headNode = newNode;
} else {
while(current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
Note the additional * wherever headNode occurs. In main:
struct Node* head;
append(&head, 'a');
printLinkedList(head);

Related

Linked list insert end node in C

I'm currently learning about linked list in C and trying to write a function to insert a node at the end and then print all the data.
At first my function did not work (only 1 2 are printed)
struct node {
int data;
struct node *link;
};
void add_end(struct node *head, int a){
struct node *current, *temp;
current = head;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = a;
temp->link = NULL;
while(current != NULL){
current = current->link;
}
current = temp;
};
int main()
{
struct node *head;
head = (struct node *)malloc(sizeof(struct node));
head->data = 1;
head->link = NULL;
struct node *current;
current = (struct node *)malloc(sizeof(struct node));
current->data = 2;
current->link = NULL;
head->link = current;
add_end(head, 3);
current = head;
while(current != NULL){
printf("%d\n", current-> data);
current = current->link;
}
return 0;
}
After a while fixing it worked ( 1 2 3 are printed )
void add_end(struct node *head, int a){
struct node *current, *temp;
current = head;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = a;
temp->link = NULL;
while(current->link != NULL){
current = current->link;
}
current->link = temp;
};
Can anyone tell me why the first one did not work pls. I thought they are the same because in the first version: current is the link of the last node which is the address of the next node (null) and in the second version: current->link is the link of the last node, which is the address of the next node (null) as well.
Once current is NULL you have already passed the last node in the list, and current is a NULL pointer.
Assigning to it will not add the node to the list, it will just reassign current to no longer be a NULL pointer, but the last nodes link will not have been modified.
With the second function you find the actual last node in the list, and append the new node to the end.

C: Problems with Reversing a linked list

I'm writing a program to create a linked list(a node), then reverse it. The linked list contains data and the address of the next.
typedef struct node{
int data;
struct node *next;
}node;
Firstly, I create the linked list.
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
After that, i create a function to print these data. (i called it PrintNode)
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
Finally, a function created to reverse the linked list.
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
It's my full program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
struct node *Insert_value(int dataInput,node* head);
struct node * Reversing(node **head);
void PrintNode(node *head);
main()
{
node *head = NULL;
int i=0,dataInput;
while(i!=5)
{
printf("input your elements: ");
scanf("%d",&dataInput);
head = Insert_value(dataInput,head);
i++;
}
PrintNode(head);
head = Reversing(&head);
PrintNode(head);
}
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
void PrintNode(node* head)
{
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
After debugging lots of times, I know that these functions are fine. However, after the reverse function, the address of the next node of the head variable is NULL. Can you explain and give me some pieces of advice?
The one line change that will solve your problem will be (you visualized it a bit wrong).
current->next =previous;
in place of
previous->next = current;
Your code will blowup for single element linked list. Add a proper check for that in the function Reversing(). In case there is single element first->next will be NULL. But you wrote first->next->next which will be undefined behavior in case first->next is NULL.
In earlier case you were just creating a linked list in Reversing() with the links unchanged but head was pointing to the last node. So the next of it was NULL.
Modify Reversing such that new nodes are appended at the end. When going through the list, you need to save the next node ahead of time (node *next = current->next)
struct node* Reversing(node **head)
{
node *current = *head;
node *reverse = NULL;
while(current)
{
node *next = current->next;
if(!reverse)
{
reverse = current;
reverse->next = NULL;
}
else
{
current->next = reverse;
}
reverse = current;
current = next;
}
return reverse;
}

Linked list troubles list not linking to head pointer

I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.

Inserting In a Doubly LinkedList

I am trying to insert into a doubly linked list. I am then trying to print the list in both forward and reverse direction. I have created a head node and I am trying to insert another one, but I am unable to do so. The program shows a runtime error.
Please find my code below. Any help would be appreciated.
#include<stddef.h>
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
struct node *prev;
};
void insertAfter(struct node *node, int new_data){
if (node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct node* new_node = (struct node*)malloc(sizeof(struct node));
node->data = new_data;
node->next = new_node;
new_node->prev = node;
new_node->next - node->next;
if(new_node->next!=NULL)
new_node->next->prev = new_node;
}
void printlist(struct node *node){
struct node *last;
printf("Traversal in forward direction\n");
while(node!=NULL){
printf("%d\n",node->data);
last = node;
node=node->next;
}
printf("Traversal in backward direction\n");
while(last!=NULL){
printf("%d\n",last->data);
last=last->prev;
}
}
int main()
{
struct node *head;
struct node *tail;
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
There are several problems here.
First, as pointed out by #Igor, you are not allocating any memory for your head and tail nodes. You should also set tail->prev = head.
Second, the order in which insertAfter sets the link pointers causes node->next to be overwritten before it is used in setting new_node->next. This causes new_node->next to point back to new_node instead of to whatever was following node. You should set new_node->next and new_node->prev before you modify node. It also appears that you have used a minus sign instead of an equals in the "assignment" of new_node->next.
Third, in printlist, you should initialize last to NULL in case the list is empty; otherwise, you will attempt to walk the list backwards from an undefined starting (ending) point.
You want new_node->next to be the same as new_node?
if not, you'd better swap these two lines, in InsertAfter:
node->next = new_node;
new_node->next - node->next;
You need to allocate memory for your pointers head and tail.
int main()
{
struct node *head;
struct node *tail;
head = malloc(sizeof(struct node)); //allocating memory to head
tail = malloc(sizeof(struct node)); //allocating memory to tail
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
Also, never cast the return value of malloc, therefore change:
struct node* new_node = (struct node*)malloc(sizeof(struct node));
to
struct node* new_node = malloc(sizeof(struct node));

Inserting item into a linked list

I'm trying to add to my linked list only if the item I'm inserting isn't already in the link list but when I try to traverse it and print out all of the items nothing is printing out. I can't seem to see what I'm doing wrong. Any help would be appreciated
// my add function
void add(char *val)
{
printf("%s", val);// val is getting printed so i know its being passed in.
if(head == NULL){
struct node *new_node = (struct node *)malloc(sizeof(struct node));
head = new_node;
head->item = val;
head->next = NULL;
} else{
struct node *current = head;
struct node *newNode = (struct node *) malloc(sizeof(struct node));
if (newNode == NULL) {
exit(-1);
}
newNode->item = val;
newNode->next = NULL;
while (current != NULL) {
current = current->next;
}
current = newNode;
}
}
//my traverse function
void goThroughList() {
struct node *current = head;
while(current != NULL){
printf("%s\n",current->item);
current= current->next;
}
}
add doesn't successfully add anything once head has been assigned. It only updates a local current pointer. You could fix that by changing the code that searches for the tail of the list to
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
If this doesn't help, can you update your question to show how add is being called? (To rule out the possibility that the same char array is being used for multiple calls, leaving all nodes with their item pointers pointed to the same buffer.
Also, there is no code I can see that checks for duplicates. You could implement this inside the branch of add where head already existed by iterating through the list using strcmp to compare each node's item with val.
your add function is incorrect
try this one :
void add(char *val)
{
printf("%s", val);// val is getting printed so i know its being passed in.
if(head == NULL){
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->item = val;
new_node->next = NULL;
head = new_node;
}
else{
struct node *current = head;
while (current->next != NULL) {
if(strcmp(current->item, val) == 0)
return;
current = current->next;
}
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->item = val;
new_node->next = NULL;
current->next = new_node;
}
}
what list does this function go trought ?
void goThroughList() {
struct node *current = head;
while(current != NULL){
printf("%s\n",current->item);
current= current->next;
}
}
try this instead :
void goThroughList(struct node* llist)
{
if(llist)
{
printf("%s" , llist->item);
goThroughList(llist->next);
}
}

Resources