What is the logical error in my attempt to implement the insertion of nodes in the linked list? - c

I'm unable to get an output for inserting nodes at the beginning, end, and after a given node. I'm not very sure if there is anything that I missed out in the main(). I'm unable to point out my logical error in the program
`
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
//Inserts at the begining
void push(struct node **head, int x){
struct node *newnode = (struct node *)malloc(sizeof(struct node));
newnode->data = x;
*head = newnode;
newnode->next = (*head);
*head = newnode;
}
//Insert at the last
void append(struct node **head, int x){
struct node *temp;
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = 0;
if(*head == 0){
*head = newnode;
}
temp = *head;
while(temp->next != 0){
temp = temp->next;
}
temp->next = newnode;
}
//inserting at a given node
void insertAfter(struct node* temp, int x){
if(temp == NULL){
printf("previous node cannot be NULL");
}
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = temp->next;
temp->next = newnode;
}
void printList(struct node *temp){
while(temp->next != NULL){
printf("%d",temp->data);
}
temp = temp->next;
}
int main(){
struct node *head = NULL;
append(&head,6);
push(&head, 7);
push(&head, 1);
append(&head, 4);
insertAfter(head->next, 8);
printf("Created linked list is:\n");
printList(head);
return 0;
}
`
The output is 1 7 8 6 4
But I'm getting no output and no errors as well

Within the function print_list there can be an infinite loop because this statement
temp = temp->next;
is placed after the while loop
void printList(struct node *temp){
while(temp->next != NULL){
printf("%d",temp->data);
}
temp = temp->next;
}
The function can look for example the following way
void printList( const struct node *head )
{
for ( ; head != NULL; head = head->next )
printf( "%d -> ", head->data );
}
puts( "null" );
}
Pay attention to that within the function push this statement
*head = newnode;
is present twice.
Also the functions are unsafe because there is no check whether memory was allocated successfully within the functions.
For example the function append could be declared and defined the following way
//Insert at the last
int append( struct node **head, int x )
{
struct node *newnode = malloc( sizeof( *newnode ) );
int success = newnode != NULL;
if ( success )
{
newnode->data = x;
newnode->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = newnode;
}
return success;
}

Related

Duplicating a linked list without using recursion

I'm trying to figure out how to duplicate a linked list, and after debugging on Vs code I'm getting a segmentation fault on cuurent->data = temp->data;
and I'm not sure why this is happening.
and this is the code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head;
struct node* head2;
struct node* Insert(struct node* head, int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = head;
return temp;
}
void Print(struct node* head)
{
struct node* tmp1 = head;
printf("List is:");
while (tmp1 != NULL) {
printf(" %d", tmp1->data);
tmp1 = tmp1->next;
}
printf("\n");
}
struct node* dupe(struct node* head, struct node* head2)
{
if (head == NULL)
return NULL;
struct node* temp = head;
struct node* prev = NULL;
struct node* cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
if (head2 == NULL) {
cuurent->next = head2;
head2 = cuurent;
}
while (temp != NULL) {
temp = temp->next;
cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
cuurent->next = prev;
prev = cuurent;
}
return head2;
}
int main(void)
{
head = NULL;
head2 = NULL;
head = Insert(head, 4);
head = Insert(head, 2);
head = Insert(head, 3);
head = Insert(head, 5);
head2 = dupe(head, head2);
Print(head);
Print(head2);
}
As pointed out in the comments,
while (temp != NULL) {
temp = temp->next;
changes the value of temp immediately after guarding against a null pointer value.
This eventually means
cuurent->data = temp->data;
will cause Undefined Behaviour by dereferencing temp when it is the null pointer value.
You can apply the exact same looping principles shown in Print to copy the list. The only difference being you must save a pointer to the first node.
The same principle can be used again when it comes time to free the memory.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *next, int x)
{
struct node *n = malloc(sizeof *n);
n->data = x;
n->next = next;
return n;
}
void print_list(struct node *head)
{
printf("List is: ");
while (head) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
void free_list(struct node *head)
{
struct node *t;
while (head) {
t = head->next;
free(head);
head = t;
}
}
struct node *copy_list(struct node *head)
{
struct node *root = NULL;
for (struct node *current; head; head = head->next) {
struct node *new = insert(NULL, head->data);
if (!root)
root = new;
else
current->next = new;
current = new;
}
return root;
}
int main(void)
{
struct node *head = NULL;
head = insert(head, 4);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 5);
struct node *head2 = copy_list(head);
print_list(head);
print_list(head2);
free_list(head);
free_list(head2);
}
Output:
List is: 5 3 2 4
List is: 5 3 2 4

Segmentation fault in linked list program (c language)

I'm trying to write a code for linked lists using c++. Insert at begin and Insert at end are not working for some reason. Here is the code.
`
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void insertAtBeginning(int );
void insertAtEnd(int );
void printLL();
struct Node
{
int data;
struct Node *link;
};
struct Node *head;
int main()
{
struct Node *temp, *newnode;
int ch=1, i=1, info;
head = NULL;
while(ch)
{
printf("Enter data: ");
scanf("%d", &info);
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = info;
newnode->link = NULL;
if(head == NULL)
{
head = newnode;
temp = newnode;
}
else
{
temp ->link = newnode;
temp = newnode;
}
printf("You wish to continue? (press 0 to terminate)\n");
scanf("%d",&ch);
if(!ch)
{
break;
}
}
temp = head;
while(temp!=NULL)
{
printf("%d -> ",temp->data);
temp = temp->link;
}
printf("\n");
insertAtBeginning(50);
insertAtEnd(150);
//printLL();
}
void insertAtBeginning(int info)
{
struct Node *newnode;
newnode->data = info;
printf("\n%d\n", newnode ->data);
newnode->link = head;
head = newnode;
}
void insertAtEnd(int info)
{
struct Node *temp, *newnode;
newnode->link = NULL;
newnode->data = info;
temp = head;
while(temp!=NULL)
{
temp = temp->link;
}
temp->link = newnode;
printf("\n%d\n", newnode -> data);
}
void printLL()
{
struct Node *temp;
temp = head;
while(temp!=NULL)
{
printf("%d -> ",temp->data);
temp = temp->link;
}
}
`
The problem is somewhere around newnode->data = info in the functions.
I created two functions, one to insert an element at beginning and one to insert an element at end. In both of them, i've created a newnode. The problem is I cannot insert data into those nodes.
When you want to append a new node to the end of a linked list, you must find your last node (a node which its link is NULL, not itself). Also, it is better to use meaningful variable name (temp is too general name). You also forgot to malloc new nodes in insertAtBeginning and insertAtEnd functions. I've fixed these issues in the following code
#include<stdio.h>
#include<stdlib.h>
void insertAtBeginning(int );
void insertAtEnd(int );
void printLL();
struct Node
{
int data;
struct Node *link;
};
struct Node *head = NULL;
int main()
{
struct Node *it, *newnode, *tail;
int ch=1, i=1, info;
while(ch){
printf("Enter data: ");
scanf("%d", &info);
newnode = malloc(sizeof(struct Node));
newnode->data = info;
newnode->link = NULL;
if (head == NULL) {
head = newnode;
tail = newnode;
} else {
tail->link = newnode;
tail = newnode;
}
printf("You wish to continue? (press 0 to terminate, else to continue)\n");
scanf("%d",&ch);
if(ch == 0) {
break;
}
}
it = head;
while(it != NULL) {
printf("%d -> ",it->data);
it = it->link;
}
printf("\n");
insertAtBeginning(50);
insertAtEnd(150);
}
void insertAtBeginning(int info)
{
struct Node *newnode;
newnode = malloc(sizeof(struct Node));
newnode->data = info;
printf("\n%d\n", newnode->data);
newnode->link = head;
head = newnode;
}
void insertAtEnd(int info)
{
struct Node *it, *newnode;
newnode = malloc(sizeof(struct Node));
newnode->link = NULL;
newnode->data = info;
it = head;
while(it->link != NULL)
{
it = it->link;
}
it->link = newnode;
printf("\n%d\n", newnode->data);
}
void printLL()
{
struct Node *it;
it = head;
while(it!=NULL)
{
printf("%d -> ",it->data);
it = it->link;
}
}
You're treating your uninitialized stack variable (struct Node *newnode) as a pointer to a struct Node and trying to update its fields:
struct Node *newnode;
newnode->data = info;
This doesn't work because the value of newnode is whatever garbage was on the stack beforehand, and trying to deref it (*newnode) will likely give a seg fault since you're trying to read from some unknown memory address.
Notice how inside main, you assign a result from malloc to newnode, this means you know that (given that malloc didn't return NULL), the pointer is valid, and you're free to use the memory it points to.

Segmentation fault in a simple linked list?

I am trying to implement a simple linked list. When I tried compiling its not showing any errors. But when while running it, its giving segmentation fault. I analysed the code but I'm not able to find any fault, might be wrong in my side, I don't know.
Please help me find the fault in the code.
Thanks in advance for all the suggestions
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node* next;
};
void push(struct node** first, int data){
struct node* new_node;
new_node =(struct node*)malloc(sizeof(struct node));
/*printf("Enter the data\n");
scanf("%d",&new_node->data);*/
new_node->data = data;
new_node->next= NULL;
if(*first==NULL){
*first = new_node;
return;
}
new_node->next= *first;
*first = new_node;
}
void insert_node(struct node* prv, int data){
if(prv==NULL){
printf("previous node cannot be null\n");
return;
}
struct node* new_node;
new_node = (struct node*)malloc(sizeof(struct node));
/* printf("Enter the data\n");
scanf("%d",&new_node->data); */
new_node->data = data;
new_node->next = prv->next;
prv->next = new_node;
}
void append(struct node** first, int data){
struct node* last;
last = (struct node*)malloc(sizeof(struct node));
/* printf("Enter the data\n");
scanf("%d",&last->data); */
last->data = data;
last->next = NULL;
struct node* pre = *first;
if(*first == NULL){
*first = last;
}
while(pre->next!=0)
{pre = pre->next;}
last->next = pre->next;
pre->next = last;
}
void print(struct node* first){
if(first==NULL){
printf("There is no linked list to print\n");
}
while(first!=NULL){
printf("%d ",first->data);
first = first->next;
}
printf("\n");
}
int main()
{
struct node* first=NULL;
append(&first, 6);
push(&first, 7);
push(&first, 1);
append(&first, 4);
insert_node(first->next, 8);
printf("The Linked List is: \n");
print(first);
return 0;
}
You got your segv inside the append function:
void append(struct node** first, int data){
struct node* last;
last = (struct node*)malloc(sizeof(struct node));
last->data = data;
last->next = NULL;
struct node* pre = *first; // <-- pre = NULL
if(*first == NULL){
*first = last;
}
while(pre->next!=0)
{pre = pre->next;} //<-- referencing NULL
last->next = pre->next;
pre->next = last;
}
Solution: add a return inside the if.
if(*first == NULL){
*first = last;
return;
}

Linked list implementation in C(printing only last two nodes)

#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
void addLast(struct node **head, int value);
void printAll(struct node *head);
struct node *head1 = NULL;
int main() {
addLast(&head1, 10);
addLast(&head1, 20);
addLast(&head1, 30);
addLast(&head1, 40);
printAll(head1);
return 0;
}
void addLast(struct node **head, int value) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
(*head)->next = NULL;
} else {
struct node **temp = head;
while ((*temp)->next != NULL) {
*temp = (*temp)->next;
}
(*temp)->next = newNode;
newNode->next = NULL;
}
}
void printAll(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d->", temp->data);
temp = temp->next;
}
printf("\n");
}
addLast() will append the new node at the end of the list, with printAll(), I am printing entire list.
Every time when I am printing the list, I can only see the last two nodes.
Can anyone please help, why loop is not iterating over entire list ?
The function addLast is too complicated and as result is wrong due to this statement
*temp = (*temp)->next;
in the while loop. It always changes the head node.
Define the function the following way
int addLast( struct node **head, int value )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = value;
newNode->next = NULL:
while( *head ) head = &( *head )->next;
*head = newNode;
}
return success;
}
Take into account that there is no need to declare the variable head1 as global. It is better to declare it inside the function main.
Also all the allocated memory should be freed before exiting the program.

Why the following implementation overrides the elements/ or prints only one element

I am trying to implement linked list in c. In the insertion of the element, if the head is not NULL, I am trying to add a node in the beginning of the linked list
Here is my code
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node* next;
};
struct Node* head ;
void insert(int data){
struct Node* temp = (struct Node*) malloc(sizeof(struct Node));
temp->data = data;
if(head!=NULL){
temp = head;
head = temp;
}
temp -> next = NULL;
head = temp;
}
void print(){
struct Node* temp = head;
while(temp!=NULL){
printf("%d \n",temp->data);
temp = temp->next;
}
}
int main(){
head = NULL;
insert(2);
insert(3);
insert(5);
print();
return 0;
}
But on print function, I am getting only 2 as output. What might be the reason?
The function should be defined the following way
void insert( int data )
{
struct Node *temp = ( struct Node * )malloc( sizeof( struct Node ) );
if ( temp != NULL )
{
temp->data = data;
temp->next = head;
head = temp;
}
}
Or the following way
_Bool insert( int data )
{
_Bool success;
struct Node *temp = ( struct Node * )malloc( sizeof( struct Node ) );
if ( ( success = temp != NULL ) )
{
temp->data = data;
temp->next = head;
head = temp;
}
return success;
}
As for your code then you always assign head itself when it is not the first node
if(head!=NULL){
temp = head;
head = temp;
}
And as result the program has memory leaks and the list contains always the first inserted element.
Of course you need to write also a function that will free all allocated memory when the list is not needed any more.
this may be the insert function
void insert(int n)
{
if(head==NULL)
{
head=(struct Node*)malloc(sizeof(struct Node));
head->data=n;
head->next=NULL;
}
else
{
struct Node *temp=(struct Node*)malloc(sizeof(struct Node));
temp->data=n;
temp->next=head;
head=temp;
}
}

Resources