Linked List Program is crashing again and again - c

I have made a sorted linked list program. I don't know why, but it is crashing again and again. Tried to fix it but, didn't work. The problem seems to be in a print_list function, but don't know what's the problem.
here's my code.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node{
struct node *next;
int val;
};
struct LLADT{
struct node *head;
};
void init(struct LLADT *LL){
LL-> head = 0;
}
// Printing a linked list
void print_list(struct LLADT *LL){
struct node *temp;
temp = LL-> head;
while(temp ->next!=NULL){ // changed temp!=NULL to temp->next!=NULL
printf("%d\n", temp->val);
temp = temp -> next;
}
}
//inserting sorted elements
void sortInsert(struct LLADT *LL, int num){
struct node *newNode;
newNode->val = num;
newNode->next = 0;
newNode =(struct node*)malloc(sizeof(struct node));
// Case -1: List is empty
if(LL->head == 0){
LL->head = newNode;
}
else{
struct node *curr;
curr = LL->head;
struct node *prev;
prev = NULL;
// Traversing list to find the insert location
while(curr != 0){
if(curr->val >= newNode->val){
break;
}
else{
prev = curr;
curr = curr -> next;
}
// Case-2:
if(curr == LL->head){
newNode->next = LL->head;
LL->head = newNode;
}
// case-3
else{
newNode->next = curr;
prev->next = newNode;
}
}
}
}
int main(){
struct LLADT LL;
sortInsert(&LL,17);
sortInsert(&LL,3);
sortInsert(&LL,5);
sortInsert(&LL,2);
sortInsert(&LL,1);
sortInsert(&LL,20);
//print_list(&LL);
getch();
return 0;
}
using codeblocks.

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node{
struct node *next;
int val;
};
/*struct LLADT{
struct node *head;
};*/
struct node * head ;
void init(){
head = NULL;
}
// Printing a linked list
void print_list(){
struct node *temp;
temp = head;
while(temp !=NULL){
printf("%d\n", temp->val);
temp = temp -> next;
}
}
//inserting sorted elements
void sortInsert(int num){
struct node *newNode;
struct node *curr;
newNode =(struct node*)malloc(sizeof(struct node));
newNode->val = num;
newNode->next = NULL;
// Case -1: List is empty
if(head == NULL){
head = newNode;
}
else{
curr=head;
while(curr->next!=NULL){
curr=curr->next;
}
curr->next=newNode;
// Traversing list to find the insert location
// while(curr != NULL){
// if(curr->val >= newNode->val){
// break;
// }
// else{
// prev = curr;
// curr = curr -> next;
// }
// Case-2:
// if(curr == LL->head){
// newNode->next = LL->head;
// LL->head = newNode;
//}
// case-3
//else{
// newNode->next = curr;
// prev->next = newNode;
// }
//}
}
}
int main(){
//struct LLADT LL;
sortInsert(17);
sortInsert(3);
sortInsert(5);
sortInsert(2);
sortInsert(1);
sortInsert(20);
print_list(head);
getch();
return 0;
}
You can try this code as there is no need to declare other struct for head
Commented out your unwanted code

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.

Expected expression before 'Node'

I've been messing aroung with the linked list implementation in C and got stuck at this problem: why is it giving me expected expression before 'Node' in the following lines?:
Node *newNode1= malloc(sizeOf(Node));
Node *newNode2= malloc(sizeOf(Node));
Node *newNode3= malloc(sizeOf(Node));
Node *newNode4= malloc(sizeOf(Node));
I've never seen such problems in C before. What went wrong ?
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node_{
int data;
struct Node_ *next;
}Node;
void insertNodeBegin(Node **head, Node *newNode){
if((*head)==NULL){
(*head)->next = NULL;
*head = newNode;
}
else{
newNode->next = (*head)->next;
(*head)->next = newNode;
}
}
void printList(Node *head){
Node *current = head;
while(current != NULL){
printf("%d ", current->data);
current = current->next;
}
}
int main()
{
Node *head = NULL;
Node *newNode1= malloc(sizeOf(Node));
newNode1->data = 12;
Node *newNode2 = malloc(sizeOf(Node));
newNode2->data = 16;
Node *newNode3 = malloc(sizeOf(Node));
newNode3->data = 55;
Node *newNode4 = malloc(sizeOf(Node));
newNode4->data = 8;
insertNodeBegin(&head, newNode1);
insertNodeBegin(&head, newNode2);
insertNodeBegin(&head, newNode3);
insertNodeBegin(&head, newNode4);
printList(head);
return 0;
}
sizeOf(Node) should be sizeof(Node), note the small o. After all this is C, not Java. :)
In short reorder if commands inside insertNodeBegin()
if(*head == NULL){
*head = newNode;
(*head)->next = NULL;
}
Because in first execution of program head points to NULL and for it we haven't any allocated memory. As head in first execution not points to a Node location using head -> next not valid and cause segmentation fault in run time.
In node creation with malloc() we must check is memory allocation successful or not. for that i use createNode() function.
We check if memory allocation for Node is OK then add that Node to list. And finally Use void as main(void) argument.
After these change your code becomes
Code
#include <stdio.h>
#include <stdlib.h>
typedef struct Node_{
int data;
struct Node_ *next;
}Node;
void insertNodeBegin(Node **head, Node *newNode){
if(*head == NULL){
*head = newNode;
(*head)->next = NULL;
}
else{
newNode->next = (*head)->next;
(*head)->next = newNode;
}
}
void printList(Node *head){
Node *current = head;
while(current != NULL){
printf("%d ", current->data);
current = current->next;
}
}
int createNode(Node **node, int value){
*node = malloc(sizeof(Node));
if(*node){
(*node)->data = value;
return 1;
}else{
fprintf(stdout, "%s", "can't allocate ...\n");
return 0;
}
}
int main(void)
{
Node *head = NULL;
Node *newNode1;
Node *newNode2;
Node *newNode3;
Node *newNode4;
if(createNode(&newNode1, 12)) {
insertNodeBegin(&head, newNode1);
}
if(createNode(&newNode2, 16)) {
insertNodeBegin(&head, newNode2);
}
if(createNode(&newNode3, 55)) {
insertNodeBegin(&head, newNode3);
}
if(createNode(&newNode4, 8)) {
insertNodeBegin(&head, newNode4);
}
printList(head);
return 0;
}

Reversing a Singly Linked List

I know there are multiple questions on the same problem on SO. But somewhere, I am not able to get the logic.
The function that reverses the Linked List is as follows:
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
I am using a global head pointer and the structure of a node in the linked list is:
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
Here, every time the curr node will point to the prev node and at the end when the list is traversed by the curr node, prev node will point to the last node in the list which I make as the head pointer.
But, this logic doesn't reverse the list and only prints the first node. So, I think the code is executed only once but I am not able to catch the mistake.
The other functions to make the program complete:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
void add(int n)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = n;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
temp->next = head;
head = temp;
}
void print()
{
struct node *temp = head;
printf("\n The List is : ");
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp = temp->next;
}
}
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
int main(void)
{
add(1);
add(2);
add(3);
add(4);
add(5);
print();
reverse();
print();
return 0;
}
You are overwriting the curr->next pointer which is then used to iterate the list. Code should be more like this:
void reverse()
{
struct node *curr=head, *prev=NULL;
struct node *next;
while(curr!=NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}

I am creating a garbage node at the end of linked list just to specify NULL. How can I modify my code to prevent that?

#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
Node* temp = head;
if(head -> next == NULL){
head ->val = val;
head -> next = newNode;
}
else{
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}
As I said in the question, I'm creating a useless node at the end just to specify NULL. How can I remove that feature? I know I'm doing something wrong in the add_at_end function but I'm not able to rectify it. Help would be appreciated. Thanks
EDIT:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
typedef struct List{
Node* head;
} List;
void add_at_end(List* l, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
newNode -> val = val;
Node* temp = l->head;
if(temp == NULL){
l->head = newNode;
}
else{
while(temp->next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
}
}
void display(List* l){
Node* t = l -> head;
while(1){
printf("%d\n", t->val);
if(t->next == NULL) break;
t = t->next;
}
}
int main(){
List l;
l.head = NULL;
add_at_end(&l, 10);
add_at_end(&l, 20);
add_at_end(&l, 30);
display(&l);
return 0;
}
This is my final code.
I need help adding nodes to the middle of the list. How can I do that?
Your node usage is all confused. When you create a new node the value should be stored into that node and the node linked into the list. Instead what you are doing is trying to add the value into the last node and then linking in a dummy node. It's a bit convoluted so I'm not sure I've explained what you have done clearly. Here is what add_to_end should be more like:
add_to_end (Node** head, int val)
{
Node* temp;
Node* newNode = malloc(sizeof(Node));
if (!newNode) {
/* Error */
}
newNode->val = val;
newNode->next = NULL;
if (!*head) {
/* empty list. Just make new node the head */
*head = newNode;
} else {
/* Find the end of the list */
temp = *head;
while (temp->next) {
temp = temp->next;
}
/* temp is now the last node. Chain new node after it */
temp->next = newNode;
}
}
Instead of a null node, you can represent the end of the list with a value of NULL, i.e. with a null pointer. The list is empty when head is NULL and the last node has node->next == NULL.
For this to work, you must be able to update the head when you add a node, because after inserting the frst node, the head will no longer be NULL. (The same goes for inserting at the front or deleting the first node.)
This chan be achieved by passing a pointer to a node pointer:
void add_at_end(Node **head, int val)
{
Node* newNode = malloc(sizeof *newNode);
newNode->next = NULL;
newNode->val = val;
while (*head) {
head = &(*head)->next;
}
*head = newNode;
}
Then you call add_at_and like this:
Node *head = NULL;
add_at_end(&head, 1);
add_at_end(&head, 2);
add_at_end(&head, 3);
It is important that head is initialised to NULL. More generally, all your pointers should either be NULL or point to valid nodes.
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = (Node *)malloc(sizeof(Node));
newNode -> next = NULL;
if(head == NULL)
{
head = new_node;
head->val = val;
}
if(head -> next == NULL)
{
new_node ->val = val;
head -> next = newNode;
}
else{
Node *temp = head;
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}

Resources