Why is (null) being printed in my c code? - c

I am trying to add strings to a linked list but I have a problem with (null) being printed. Anyone who can help me?
The best I could do is narrow it down to this being the problem:
struct node *head = malloc(sizeof(struct node));
struct node *ptr = malloc(sizeof(struct node));
Here is the code:
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
struct node *link;
};
struct node *add_begin(char *d, struct node *head) {
struct node *ptr = malloc(sizeof(struct node));
ptr->data = d;
ptr->link = head;
return ptr;
}
void add_end(struct node *point, char *data) {
struct node *temp = malloc(sizeof(struct node));
temp->data = data;
temp->link = NULL;
while (point->link != NULL) {
point = point->link;
}
point->link = temp;
}
int main() {
struct node *head = malloc(sizeof(struct node));
struct node *ptr = malloc(sizeof(struct node));
head->link = ptr;
char *data = "Chocolate Cake";
head = add_begin(data, head);
add_end(ptr, data);
while (head != NULL) {
printf("%s \n", head->data);
head = head->link;
}
}
Output:
Chocolate Cake
(null)
(null)
Chocolate Cake

The problem is you allocate dummy nodes, which are uninitialized and happen to have null pointers as data and link. The list should be initially empty, ie: head should be a null pointer.
Note that add_end should also return the head pointer in case an empty list was passed. Passing the arguments in the same order to both functions is highly recommended.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
struct node *link;
};
struct node *add_begin(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = head;
return ptr;
}
struct node *add_end(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = NULL;
if (head == NULL) {
return ptr;
} else {
struct node *temp = head;
while (temp->link != NULL) {
temp = temp->link;
}
temp->link = ptr;
return head;
}
}
int main() {
struct node *head = NULL;
char *data = "Chocolate Cake";
head = add_begin(head, data);
head = add_end(head, data);
for (struct node *ptr = head; ptr; ptr = ptr->link) {
printf("%s\n", ptr->data);
}
return 0;
}
Output:
Chocolate Cake
Chocolate Cake

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

Linked list traversal after reversing the linked list

I've been trying to run this linkedListTraversal() function after reversing the linked list using the function reverseLinkedList(). I know that I'm applying the correct logic in the reverseLinkedList() function. But for some reason i'm getting the output as something like this
Here's my code
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
// struct Node *head;
void linkedListTraversal(struct Node *ptr)
{
// struct Node *ptr = head;
while (ptr != NULL)
{
printf("Element: %d\n", ptr->data);
ptr = ptr->next;
}
}
void reverseLinkedList(struct Node *head)
{
struct Node *prevNode = NULL;
struct Node *currNode = head;
struct Node *nextNode;
while (currNode != NULL)
{
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
}
int main()
{
struct Node *head;
struct Node *second;
struct Node *third;
head = (struct Node *)malloc(sizeof(struct Node));
second = (struct Node *)malloc(sizeof(struct Node));
third = (struct Node *)malloc(sizeof(struct Node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printf("Linked list before reversal: \n");
linkedListTraversal(head);
reverseLinkedList(head);
printf("Linked list after reversal: \n");
linkedListTraversal(head);
return 0;
}
You're not passing back the updated head to main.
The easiest way is to return the head:
struct Node *reverseLinkedList(struct Node *head);
And have main do:
head = reverseLinkedList(head);
Side note: No need to cast the results of malloc: Do I cast the result of malloc? Here's a more idiomatic way to allocate (e.g.):
head = malloc(sizeof(*head));
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
// struct Node *head;
void
linkedListTraversal(struct Node *ptr)
{
// struct Node *ptr = head;
while (ptr != NULL) {
printf("Element: %d\n", ptr->data);
ptr = ptr->next;
}
}
struct Node *
reverseLinkedList(struct Node *head)
{
struct Node *prevNode = NULL;
struct Node *currNode = head;
struct Node *nextNode;
while (currNode != NULL) {
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
return head;
}
int
main(void)
{
struct Node *head;
struct Node *second;
struct Node *third;
head = malloc(sizeof(*head));
second = malloc(sizeof(*second));
third = malloc(sizeof(*third));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printf("Linked list before reversal: \n");
linkedListTraversal(head);
head = reverseLinkedList(head);
printf("Linked list after reversal: \n");
linkedListTraversal(head);
return 0;
}

I feel confusion in linked list.what is the solution?

Specially i feel confusion about passing the head in function.Would any one kindly explain?
#include<stdio.h>
struct node
{
int data;
struct node *next;
};
struct node *makeNode(int item)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = item;
newNode->next = NULL;
return newNode;
}
void traverse(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d ",ptr->data);
ptr = ptr->next;
}
printf("\n");
}
void push(struct node **headRef, int data)
{
struct node *newNode = makeNode(data);
newNode->next = *headRef;
*headRef = newNode;
}
void append(struct node **headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = *headRef, *temp;
if( ptr == NULL )
{
*headRef = newNode;
return;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
}
void deleteData(struct node **headRef, int key)
{
struct node *ptr = *headRef, *prevNode;
//If key is in head node
if( (ptr->data == key) && (ptr != NULL) )
{
*headRef = ptr->next;
free(ptr);
return;
}
while( (ptr != NULL) && (ptr->data!=key) )
{
prevNode = ptr;
ptr = ptr->next;
}
if(ptr == NULL)
printf("Underflow or Key not found.\n");
else
{
prevNode->next = ptr->next;
free(ptr);
}
}
int main()
{
struct node *head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d",&data);
while( data>=0 )
{
append(&head,data);
in this function , pass the address of head.
scanf("%d",&data);
}
printf("\nTraversing...\n");
traverse(head);
but in this function why i only pass the head?
printf("\n\nEnter a data to delete:\n");
scanf("%d",&data);
deleteData(&head,data);
printf("\nTraversing...\n");
traverse(head);
}
In Function traverse
void traverse(struct node *head) {
......
......
}
Traverse function has a parameter head which is of type struct node pointer.
Hence to call traverse function you must pass an argument of type struct node pointer.
In main function you defined head as struct node *head = NULL;
that's why you are making call to the function like traverse(head).
In Function append
void append(struct node **headRef, int data)
{
....
....
}
The argument headref is of type 'pointer to pointer'.
Pointer to Pointer variable stores the address of pointer
Hence, you must pass address of pointer as argument and you make call to append function as append(&head,data)
To use pointer as a parameter in append function
Change the return type of you function from void to struct node* and return the headRef pointer.
struct node* append(struct node *headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = headRef, *temp;
if( ptr == NULL )
{
headRef = newNode;
return headRef;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
return headref;
}
Inside the main function, you should call append function like this.
head = append(head,data); //since append function is now returning a pointer
Complete code to append nodes using single pointer
#include<stdio.h>
struct node
{
int data;
struct node * next;
};
struct node * makeNode(int item)
{
struct node * newNode = (struct node * ) malloc(sizeof(struct node));
newNode -> data = item;
newNode -> next = NULL;
return newNode;
}
void traverse(struct node * head)
{
struct node * ptr = head;
while (ptr != NULL)
{
printf("%d ", ptr -> data);
ptr = ptr -> next;
}
printf("\n");
}
struct node * append(struct node * headRef, int data)
{
struct node * newNode = makeNode(data);
struct node * ptr = headRef, * temp;
if (ptr == NULL)
{
headRef = newNode;
return headRef;
}
while (ptr != NULL)
{
temp = ptr;
ptr = ptr -> next;
}
temp -> next = newNode;
return headRef;
}
int main()
{
struct node * head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d", & data);
while (data >= 0)
{
head = append(head, data);
scanf("%d", & data);
}
printf("\nTraversing...\n");
traverse(head);
return 0;
}
Function append may alter the value of head (which is a pointer). The signature is therefore void append(struct node **headRef, int data); note the **, which denotes a pointer to a pointer. So you have to pass the address of the pointer in order to allow append to change the pointer, i.e. call append(&head,data).
Function traverse, in contrast, needs not to alter the value of head, so it consumes the pointer directly (and not a pointer to that pointer). The signature is therefore void traverse(struct node *head); note the single *. Hence, call it like traverse(head).
include
struct node
{
int data;
struct node *next;
};
struct node *makeNode(int item)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = item;
newNode->next = NULL;
return newNode;
}
i got bug in the above line
void traverse(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d ",ptr->data);
ptr = ptr->next;
}
printf("\n");
}
i know that there is no need to return the pointer .is it true? if it is true why need to give a return type in the following function?
struct node* append(struct node *headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = headRef, *temp;
if( ptr == NULL )
{
headRef = newNode;
return headRef;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
return headref;
}
int main()
{
struct node *head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d",&data);
while( data>=0 )
{
head=append(head,data);
scanf("%d",&data);
}
printf("\nTraversing...\n");
traverse(head);
}

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.

Linked List not printing

I am trying to create a simple linked list using C, I think I was able to construct the linked list itself, but when I try and print it, it prints the value of the last node instead of all the values in the list.
#include <stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
temp->next = NULL;
printf("%d \n", temp->d);
return 0;
}
Any help/tips would be greatly appreciated.
There are multiple problems in your code:
You are not creating the list properly. You are allocating memory for only one node and playing around with pointers improperly causing the linked list to be pointed to the same memory
You are not calling printList function at all
It is not clear why you are allocating memory again in printList whereas it should be printing the already created list
Also, no need to pass double pointer for printList as you are not modifying the list.
Though you should be understanding and doing the changes yourself, I am providing a below modified program which I hope will help you understand the mistakes in your code.
Please see the below modified version of the code
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
struct Node *createNode()
{
struct Node *newNode;
newNode = malloc(sizeof(struct Node));
if (NULL == newNode)
return NULL;
memset(newNode, 0, sizeof(struct Node));
return newNode;
}
int main()
{
struct Node *newNode = NULL;
struct Node *headNode = NULL;
struct Node *temp = NULL;
int i = 0;
int data = 0;
printf("Enter 3 numbers\n");
for( i = 0; i< 3; i++)
{
scanf("%d", &data);
newNode = createNode();
if (NULL == newNode)
break;
newNode->d = data;
if (headNode == NULL)
{
headNode = newNode;
temp = newNode;
}
else
{
temp->next = newNode;
temp = temp->next;
}
}
printList(headNode);
return 0;
}
Replace your code with the following code :-
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp->next!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
printList(head);
return 0;
}
Here you need to declare the newNode in the loop also while taking the input. As, the current value is over-writted, the old value is lossed and only the value of last node is printed.
Also while printing, check for temp->next!=Null instead of temp!=NULL

Resources