Linked list program only printing last two nodes of list - c

I wrote a program to create and print a single linked list. I have used structure pointer to structure pointer for modifying the list. When I print the list it only prints last two nodes added.
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
struct node * createnode(int num){
struct node * n;
n=(struct node*)malloc(sizeof(struct node));
n->data=num;
n->next=NULL;
return n;
}
void createlist(struct node **head,int num){
struct node *temp=createnode(num);
*head=temp;
return;
}
void options(){
printf("Enter your choice\n");
printf("1.Add at end\n");
printf("2.Add at beginning\n");
printf("3.Add at location\n");
printf("4.Print list\n");
}
void add_end(struct node **head){
int info;
printf("Value: ");
scanf("%d",&info);
if(*head==NULL){
createlist(head,info);
return;
}
struct node *temp=createnode(info);
struct node **end=head;
while((*end)->next!=NULL){
(*end)=(*end)->next;
}
(*end)->next=temp;
}
void print2(struct node *head){
struct node * temp=head;
printf("\nList :");
while(temp!=NULL){
printf("%d ",temp->data);
temp=temp->next;
}
printf("\n");
}
int main(){
struct node *head=NULL;
createlist(&head,5);
int choice=0;
options();
scanf("%d",&choice);
while(1){
switch(choice){
case 1:add_end(&head);
break;
case 4:print2(head);
break;
default:exit(0);
}
options();
scanf("%d",&choice);
}
return 0;
}
Each time, I append 5 to 6 nodes at the end of list and when I print the list, it only prints last to nodes added.
I don't know it is wrong with add_end function or print function.

Your add_line routine incorrectly searches for the last node. The end variable is a pointer to pointer, so it is in a sense equivalent to the head parameter and it is not a temporary value, as it should be. Change the last lines to something like this:
void add_end(struct node **head){
...
struct node *end = *head;
while (end->next) {
end = end->next;
// Original line overwrites the 'head': (*end)=(*end)->next;
}
end->next=temp;
}

Related

Inputting Values in the members of structure through linked list

I am working in C. Here, I have a structure Node with data members passengers and station. I have a function which inputs the passenger number and stop Name from the user.
struct Node
{
int stopNo;
int passenger;
char station[50];
struct node* next;
};
I have a function which takes the input as the name of station and passengers no and automatically increase the stopNo by 1.
I am trying to Use a linked list to store the stations.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int stopNo;
int passenger;
char station[50];
struct node* next;
};
void takeInput(struct Node* head)
{
head->stopNo = head->stopNo +1;
printf("Station Name");
scanf(" %[^\n]s",head->station);
printf("New Passengers ");
scanf("%d",&head->passenger);
}
void printStops(struct Node* head)
{
for(int i=0;i<=head->stopNo;i++)
{
printf("Stop %d. %s with %d passenger",head->stopNo,head->station,head->passenger);
}
}
int main()
{ int n;
struct Node* head = NULL;
struct Node* second = NULL;
//Memory Allocation into heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
while(1){
//Menu
printf("1.Log Stops\n");
printf("2.Print Stop");
printf("3.Exit");
scanf("%d",&n);
switch(n){
case 1:
takeInput(struct Node*);
break;
case 2:
printStops(struct Node*);
break;
case 3:
exit(0);
default:
printf("Enter the numbers from 1 to 2");
}
}
}
I am confused what to pass as an argument through the function.
You are mis-using the linked list concept.
The principle is to dynamically add new nodes at the beginning (simpler) or at the end (slightly more complex). Here, as you already have a function dedicated to feeding the list, you could just allocate the nodes there. A possible way is to pass the address of the current head, and let the function change it. But you have to define a sentinel value to tell the function that you do not want to input more nodes.
In the following code "STOP" is that sentinel:
void takeInput(struct Node **head)
{
int stopNo = 0;
for (;;) {
struct Node *node = malloc(sizeof (*node));
node->stopNo = stopNo++;
node->next = *head;
printf("Station Name");
scanf(" %[^\n]",node->station);
if (strcmp(node->station, "STOP") == 0) { // no more station
free(node);
break;
}
printf("New Passengers ");
scanf("%d",&node->passenger);
*head = node;
}
}
That way, you can iterate the list to print its content:
void printStops(struct Node* head)
{
while (head != NULL)
{
printf("Stop %d. %s with %d passenger\n",head->stopNo,head->station,head->passenger);
head = head->next;
}
}
Finally, you main would become:
int main()
{ int n;
struct Node* head = NULL;
while(1){
//Menu
printf("1.Log Stops\n");
printf("2.Print Stop\n");
printf("3.Exit\n");
scanf("%d",&n);
switch(n){
case 1:
takeInput(&head);
break;
...

linked list: how to return the whole linked list after insterting

I am trying to return the head of a linked list in the function Insert of the following program. However, it is failing with compilation error.
Can anyone please tell me what wrong I have done:
#include<stdio.h>
#include<stdlib.h>
struct ListNode
{
int data;
struct ListNode *next;
};
int ListLength(struct ListNode *head)
{
int count = 0;
struct ListNode *temp=head;
while(temp!=NULL)
{
count++;
temp=temp->next;
}
return count;
}
struct ListNode *Insert(struct ListNode *head, int value, int pos)
{
struct ListNode *temp,*curr;
curr=head;
int k=1;
temp=(struct ListNode *)malloc(sizeof(struct ListNode));
if(pos==1)
{
temp->data=value;
if(head==NULL)
{
temp->next=NULL;
head=temp;
}
else
{
temp->next=head;
head=temp;
}
}
else
{
while((curr!=NULL) && (k<pos))
{
k++;
curr=curr->next;
}
temp->data=value;
temp->next=curr->next;
curr->next=temp;
}
return head;
}
void printList(struct ListNode *head)
{
struct ListNode *temp;
temp=head;
while(temp!=NULL)
{
printf("%d",temp->data);
printf(" ");
temp=temp->next;
}
}
int main
{
struct ListNode *head=NULL;
//head = NULL;
head=Insert(head,10,1);
//Insert(head,11,2);
printList(head);
return 0;
}
I am trying to return the head of the new linked list after the insertion. I don't know where I am going wrong. Thanks in advance for the help.
(i) Firstly, include int main(void) as mentioned in the comments.
(ii) Next, with your current code, when you try printing the list, you are going to be in an infinite loop and get a stack overflow.
To avoid this, increment the temp to point to the next node after each print.
So your print function should look like:
void printList(struct ListNode *head)
{
struct ListNode *temp;
temp=head;
while(temp!=NULL)
{
printf("%d",temp->data);
printf(" ");
temp=temp->next; // this line is required
}
}
(iii) And in your main function, call the printList with an argument, that is the head of the node like this:
printList(head);
(iv) And don't forget to return the count in your finding the length of the list function. Add the return statement at the end of your ListLength function:
return count;
(v) Your current code does not handle a case when head is NULL, and user wants to insert at a position greater than 1. Or more generally, when a user wants to insert at a position that is greater than the current list's length.
While you trust such an input would not be given, always handle such exceptions (you would probably get a SEGMENTATION FAULT here when trying to access memory of null nodes).
To handle this, you can add a check at the start of the Insert function like,
int lenList = ListLength(head);
if (lenList < pos)
{
printf("Please provide a position less than %d to insert", lenList);
return 0; // don't proceed with inserting node with NULL pointers
}
If head is declared global you don't have to return it. (Sorry, my answer is short)

Deleting a nth node in a doubly linked list

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
struct node
{
int data;
struct node *prev;
struct node *next;
};
struct node* HEAD;
void Deleteatn(int c)
{
struct node *store,*store1,*temp=HEAD;
if(c==1)
{
store=temp->next;
store->prev=NULL;
HEAD=store;
free(temp);
}
else
{
for(int i=1;i<c-1;i++)
temp=temp->next;
store=temp->next;
store1=store->next;
temp->next=store->next;
//store1->prev=temp;//DOUBT
free(store);
}
}
void print()
{
struct node *temp=HEAD;
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;
}
printf("\n");
}
void Insertatend(int b)
{
struct node *n;
n=(struct node *)malloc(sizeof(struct node));
n->data=b;
n->prev=NULL;
n->next=NULL;
if(HEAD==NULL)
HEAD=n;
else
{
struct node *store,*temp=HEAD;
while(temp!=NULL)
{
store=temp;
temp=temp->next;
}
store->next=n;
n->prev=store;
}
}
int main()
{
int a,b,c;
printf("How many Numbers need to be inserted?\n");
scanf("%d",&a);
for(int i=0;i<a;i++)
{
printf("Enter a number\n");
scanf("%d",&b);
Insertatend(b);
}
printf("The List is\n");
print();
printf("Enter which node need to be deleted?\n");
scanf("%d",&c);
Deleteatn(c);
printf("The List After Deletion is\n");
print();
return 0;
}
Here I have written a program to delete a nth node in a doubly linked list ,I have a doubt that without making a Backward link,how does the output come correctly.So in doubly linked list is it not mandatory to make both forward and backward link?
I have mentioned the code line as doubt,without that code,how is it working???
You can find the issue when you traverse back.
Since you are traversing in forward direction its working fine like a singly linked list.

Linked list append function adding an extra empty node at the beginning

struct node{
char name[50];
double grade;
struct node* next;
};
void append(struct node* root){
int n;
printf("Enter the number of students: ");
scanf("%d",&n);
while(n !=0){
struct node* temp;
temp=(struct node*)malloc(sizeof(struct node));
printf("\nEnter the name of the student: ");
scanf("%s",&temp->name);
printf("\nEnter the grade for the student named %s: ",temp->name);
scanf("%f",&temp->grade);
temp->next=NULL;
if(root==NULL){
root=temp;
}else{
struct node* iterate=root;
while(iterate->next != NULL){
iterate=iterate->next;
}
iterate->next=temp;
}
n--;
}
}
int listLength(struct node* root){
struct node* temp = root;
int counter=0;
while(temp !=NULL){
counter++;
temp=temp->next;
}
return counter;
}
int main()
{
struct node* root = NULL;
append(&root);
//printList(&root);
printf("Node length: %d",listLength(&root));
return 0;
}
This is what I have so far as I'm starting out with linked lists. I tried to make it so I can append to multiple linked lists with the function. So I'd just create a different root pointer in main and call the append function with it as a parameter to add nodes.
This seems to work, however, it adds an extra empty node at the beginning of the list. This node doesn't contain any data. So for example, if I add 4 students to the list the nodeLength function would return 5.
Change this:
void append(struct node* root)
to this:
void append(struct node** root)
so that you make the changes last even when append() terminates.
Of course then you will have to use *root instead of root inside the body of that function.
PS: Do I cast the result of malloc? No.
struct node{
char name[50];
double grade;
struct node* next;
};
struct node * append(struct node* root){
int n;
printf("Enter the number of students: ");
scanf("%d",&n);
while(n !=0){
struct node* temp;
temp=(struct node*)malloc(sizeof(struct node));
printf("\nEnter the name of the student: ");
scanf("%s",&temp->name);
printf("\nEnter the grade for the student named %s: ",temp->name);
scanf("%f",&temp->grade);
temp->next=NULL;
if(root==NULL){
root=temp;
}else{
struct node* iterate=root;
while(iterate->next != NULL){
iterate=iterate->next;
}
iterate->next=temp;
root=iterate;
}
n--;
}
return root; }
int nodeLength(struct node* root){
struct node* temp = root;
int counter=0;
while(temp !=NULL){
counter++;
temp=temp->next;
}
return counter;
}
int main()
{
struct node* root = NULL;
root= append(root);
//printList(&root);
printf("Node length: %d",nodeLength(root));
return 0;
}
Check this code to understand a bit. Will explain more.
And don't cast the return type of malloc.
Here what you are doing will work fine for if you correctly changed the parameter to struct node** but yes it can be done more easily like this(example shown above). It's natural and more intuitive rather than using double pointer.

How to get data from user for linked list

I tried to create linked list in C which will allow the user to insert data, print the list and exit from the program. I can insert the data and print the list one time but when I try to print the list again it shows list as empty. The address of the header has been changed to NULL.
#include <stdio.h>
#include <stdlib.h>
struct Node* head;
struct Node
{
int data;
struct Node* next;
};
void Insert(int x)
{
struct Node* temp=(struct Node*)malloc(sizeof(struct Node));
temp->data=x;
temp->next=head;
head=temp;
}
print()
{
printf("%d",head);
printf("\nthe list is\n");
while(head!=NULL)
{
printf("%d\t",head->data);
head=head->next;
}
}
int main()
{
//head=NULL;
int n,i,x,option;
do
{
printf("\n1.Insert 2.Print 3.Exit");
printf("\nenter option:");
scanf("%d",&option);
if(option==1){
printf("\nTotal no to be entered:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nEnter the number:");
scanf("%d",&x);
Insert(x);
}}
else{
if(option==2){
print();
}
}
}while(option!=3);
}
Your print method changes the head pointer, so next time you access the list, head will point to null. You should use a different pointer for the iteration:
void print()
{
Node* iter = head;
printf("%d", iter);
printf("\nthe list is\n");
while(iter!=NULL)
{
printf("%d\t",iter->data);
iter=iter->next;
}
}
You are lopping over the linked list with the pointer head to the head of your list, so at the end of the loop, head reaches the end of the list and nothing remains to print.
To resolve the problem you need to keep head on its place (the head of the list) and loop with a second pointer loop_ptr
print()
{ Node* loop_ptr = head;// create a pointer to loop with
printf("%d",loop_ptr);
printf("\nthe list is\n");
while(loop_ptr!=NULL)
{
printf("%d\t",loop_ptr->data);
loop_ptr=loop_ptr->next;// at the end head points always to the head of your list
}
}
Nota Bene:
struct Node* next;
struct Node* head;
This is a bad practice when dealing with pointers. Unlike other data structures, a pointer must always properly initialized to avoid unexpected mess. In your case, you can do this:
struct Node* next= NULL;
struct Node* head= NULL;

Resources