linked list implementation using pointer to pointer in C - c

I am unable to append a new node in the linked list. I have already identified the problem area but after much research and trying many things I am still unable to resolve the issue.
The problem is with the for loop in insert_node(char,struct **) function and traverse(struct *) function both of which never seem to terminate:
// program that stores name of the user using linkedlist
#include<stdio.h>
#include<stdlib.h>
typedef struct LIST{
int flag;
char name;
struct LIST *next;
} LISTNODE;
LISTNODE *head=NULL,*newnode=NULL;// global pointers
LISTNODE* initialize(); //initializes struct node with default values and returns a node
void insertNode(char c,LISTNODE** temp);
void traverselist(LISTNODE *temp);
int main(){
char ans,ch;
printf("\n\nEnter your name and hit enter-\n\n");
do{
printf("your name:");
fflush(stdin);
scanf("%c",&ch);
insertNode(ch,&head);
printf("\n\ninsertnode-back to main()");
printf("Want to continue?(Y?N):");
fflush(stdin);
scanf("%c",&ans);
}while(ans=='y'||ans=='Y');
printf("\n\ntraverselist-leaving main()");
traverselist(head);
printf("\n\ntraverselist-back to main()");
return 0;
}
void insertNode(char c, LISTNODE **temp){
printf("\n\ninto insertnode: before initialize");
LISTNODE* temp2;
newnode=initialize();
printf("\n\nback to insertnode:after initialize");
//printf("\nnewnode->name=%c",newnode->name);
//printf("\nnewnode->flag=%d",newnode->flag);
newnode->name=c;
//printf("\nnewnode->name=%c",newnode->name);
//printf("\nnewnode->flag=%d",newnode->flag);
//for(;(*temp)!=NULL;temp=&(*temp)->next);
/*while((*temp)->next!=NULL){
temp=&(*temp)->next;
printf("\n\nIn while!");
}
*/
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!") ;
//printf("\n\nout of while!");
(*temp)=newnode;
}
LISTNODE* initialize(){
static int count=0;
LISTNODE *tempnewnode;
printf("\n\nINto inintialize!");
tempnewnode=(LISTNODE*)malloc(sizeof(LISTNODE));
if(tempnewnode==NULL){
printf("No memory available. Aborting!");
exit(0);
}
else{
tempnewnode->flag=0;
tempnewnode->name='*';
tempnewnode->next=NULL;
if(count==0){
head=tempnewnode;
count++;
}
}
return tempnewnode;
}
void traverselist(LISTNODE *temp){
printf("\n");
for(;temp!=NULL;temp=temp->next){
printf("%c",temp->name);
}
}
Please help!

The problem is inside the insert_node function, specifically with the loop:
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!");
You'd be better advised not to use the reference temp in your loop, as it overwrites the head->next back to itself. Create another temporary pointer.

I changed the insertNode(char, LISTNODE**) to the following:
void insertNode(char c, LISTNODE *temp){
LISTNODE** temp2=&temp;
newnode=initialize();
printf("\n\nback to insertnode:after initialize");
newnode->name=c;
for(;(*temp2)!=NULL;temp2=&(*temp2)->next)
printf("\n\nIn for!") ;
(*temp2)=newnode;
}
and function is called like this:
insertNode(ch,head);
It works just fine!

The problem is this portion of your insertNode function
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!") ;
//printf("\n\nout of while!");
(*temp)=newnode;
Here you should first check if the link list is empty or not if it is empty then you can create the new node and assign the address of it to temp.
If not then depending upon whether you want to insert the new element in the end, beginning or middle of the list you should traverse the list then perform the insertion.
For example if you want to perform insertion at the beginning then after creating the new node you should assign the address of the start pointer of the list to the next of newly created node and move the start to the new node as you have to keep track of the start pointer.

Related

Why does using free() lead to infinite looping

When I run the following code, it gives me an infinite looping result. However if I comment out the free pointer lines in the insert function i.e. free(ptr) and free(ptrnext) then it works fine. Can anybody explain why is it so?
I am pretty sure that the print and takeInput works fine, and hence can be ignored.
#include<stdio.h>
#include<stdlib.h>
typedef struct Nodes{
struct Nodes * next;
int val;
}Node;
//Function to create a linked list
Node * takeInput(){
int data;
Node *start =NULL ;
Node *tail=NULL;
printf("Enter the number of nodes");
int num,i;
scanf("%d",&num);
for(i=1;i<=num;i++){
if(start==NULL){
start=malloc(sizeof(Node));
puts("Enter data");
scanf("%d",&data);
start->val=data;
start->next=NULL;
tail=start;
}
else{
Node * ptr = malloc(sizeof(Node));
puts("Enter data" );
scanf("%d",&data);
ptr->val=data;
tail->next=ptr;
tail=tail->next;
}
}
tail->next=NULL;
return start;
}
//Function to print
void print(Node * head){
Node*ptr=head;
while(ptr!=NULL){
printf("%d->",ptr->val);
ptr=ptr->next;
}
}
//Function to insert a node in given linked list
Node * insert(Node *start){
int i,data;
puts("Enter pos");
scanf("%d",&i);
puts("Enter data");
scanf("%d",&data);
Node * ptr=malloc(sizeof(Node));
ptr->val=data;
ptr->next=NULL;
if(i==1){
ptr->next=start;
start=ptr;
free(ptr);
}
else{
Node * ptrnext=start;
while(i!=1){
ptrnext=ptrnext->next;
i--;
}
ptr->next=ptrnext->next;
ptrnext->next=ptr;
free(ptr);
free(ptrnext);
}
return start;
}
int main(void){
Node * start =takeInput();
start=insert(start);
print(start);
}
When I run the following code, it gives me an infinite looping result. However if I comment out the free pointer lines in the insert function i.e. free(ptr) and free(ptrnext) then it works fine.
This is undefined behavior. (when you don't comment the free() functions)
Once you've freed memory you must remember not to use it any more.
Note : the pointer might or might not point the same block after freeing, it's undefined behavior
so don't free the pointer unless you want to destroy or delete the node.
so don't use the free() in the insert function as you are not deleting any node.
Apart from that, I don't see any function to deallocate the memory at the end of the program.
Always make sure to deallocate the allocated memory at the end using a delete() function.
Here's a typical implementation of delete function
void delete(Node* start)
{
Node* temporary = NULL;
while(start != NULL)
{
temporary = start->next; //saving next node address
free(start); //freeing current node
start = temporary; //assigning start with next node address
}
printf("successfully destroyed the list!"); //function exit message
}
Call it at the end of main() function or when you wish to delete the entire list

Creating two link list using one function

This is a program to print two link lists using one function.
I have used two functions i.e create and display.Create() is to create the linklist and display() to display the result of linklist.
But this code is printing NULL. I'm not not getting where is the error???
`#include<stdio.h>
#include<conio.h>
struct node
{
int data;
struct node* next;
}
*start=NULL,*start1=NULL;
//to create the linklist
struct node* create(struct node* ptr)
{ int ch;
do
{
struct node* new_node=(struct node*)malloc(sizeof(struct node));
struct node* current;
printf("enter the data\n");
scanf("%d",&new_node->data);
new_node->next=NULL;
if(ptr==NULL)
{
ptr=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("Do u want to add more ");
scanf("%d",&ch);
}while(ch!=0);
return ptr;
}
//to display the linklist
void display(struct node* temp)
{
while(temp!=NULL)
{
printf("%d--->",temp->data);
temp=temp->next;
}
printf("NULL\n");
}
int main()
{
clrscr();
create(start);
display(start);
printf("\n 2nd linklist\n");
create(start1);
display(start1);
getch();
return 0;
}
First problem
current must be declared outside the do/while loop, otherwise you will get undefined behaviour because there is no guarantee that current will keep it'svalue from one iteration to the next. However with certain compilers you may get away with it.
Second problem
Calling create(start); will not modify start because variables in C are passed by value. You need to write start = create(start);. See also this SO question. In your program start is still NULL after the call to the create function. You could have found out that easily by yourself.

Segmentation fault in singly linked list C program

In this code below, when I comment out the first and second call to display() function in main, It works fine. But without commenting, after adding 2nd element it says - segmentation fault.
I am new to pointers. Please suggest what might be wrong.
#include<stdio.h>
#include<malloc.h>
//-------------------------------------------------
struct node
{
int data;
struct node *next;
}*start=NULL;
//------------------------------------------------------------
void creat()
{
struct node *new_node,*current;
new_node=(struct node *)malloc(sizeof(struct node));
printf("\nEnter the data : ");
scanf("%d",&new_node->data);
new_node->next=NULL;
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
}
//------------------------------------------------------------------
void display()
{
struct node *new_node;
printf("\nThe Linked List : ");
new_node=start;
while(new_node!=NULL)
{
printf("%d--->",new_node->data);
new_node=new_node->next;
}
printf("NULL\n\n");
}
//----------------------------------------------------
void main()
{
creat();
display();
creat();
display();
creat();
display();
}
output ->
$./a.out
Enter the data : 4
The Linked List : 4--->NULL
Enter the data : 6
Segmentation fault (core dumped)
This is happening because of current->next=new_node; in else block.
When you enter data second time start is declared global so its value persists between function call but as current is declared within fuunction it's scope is limited to function only.
So when you enter data second time current is null so accessing current->next causes segmentation fault.
So declare current node after start variable.
Second time you call creat, you are using an ininitialized current.
current_node is a local variable with auto storage. When you return from the function, it gets deleted.
Try adding
struct node* current = NULL;
right after you define start. Then, remove it from creat.
The offending code is:
current->next=new_node;
You are dereferencing a NUll pointer which is illegal.
What you should have done was to declare current as a global variable as well:
struct node
{
int data;
struct node *next;
}*start=NULL,*current=NULL;
This will fix your display issue as well.

deleting a node in linear single linked list given the start of the list

I have the following code which deletes a given node from the linear single linked list.
I want to know if we can still improve this program and does it break anytime
struct node
{
int num;
struct node *next;
} ;
typedef struct node s;
void delete(struct node *first)
{
int flag = 0;
s *ptr, *lastNodePtr = NULL, *deleteNode;
deleteNode = (s*) malloc(sizeof(s));
printf("enter the node value to delete");
scanf_s("%d",&deleteNode->num);
deleteNode->next = NULL;
for (ptr=first;ptr!=NULL;ptr=ptr->next) //at least one element exist
{
if(deleteNode->num == ptr->num)
{
flag=1;
if(ptr==first) //need to delete at first place
{
free(ptr);
first = null; //i dont think we need to do this as it points to ptr and ptr is already null.
}
else // need to delete some where middle.it can be last as well.
{
lastNodePtr->next=ptr->next;
free(ptr);
}
printf("successfully deleted..");
break;
}
lastNodePtr=ptr; // taking note of last node visited..
}
if (flag==0)
{
printf("\n Couldn't find the node");
return;
}
}
if ptr is the first element in the list to delete, you set first to null, not to the next of ptr. (sideeffect: you are not able to free the the rest of the list)
your EDITH: delete should return the new Head, better make it a struct node **first parameter which changes the first element if the first is the deleted one
BTW: never cast the result of malloc.
BTW two. why use for-loop? everybody uses while-loop with linked lists
BTW three: normal variable names for linked lists are "head", "list", "next", "prev", "last" with the nice side-affect, they are all the same length, so making it neatly aligned.
struct node
{
struct node *next;
int num;
} ;
void delete(struct node **pp, int num) {
struct node *del;
for ( ;*pp; pp= &(*pp)->next) {
if((*pp)->num == num) break;
}
if (!*pp) { printf("Couldn't find the node(%d)\n", num); return; }
del = *pp;
*pp = del->next;
free(del);
}
BTW: there is nothing wrong with for() loops; they allow you to put all the loop logic on one line.

Insert in Linked List C

I am working on a simple text editor in C. I am having troubles with inserting an element in a linked list.
Here is my structure:
struct node {
struct node *previous;
int c;
int x;
int y;
struct node *next;
}*head;
Here is my insertion code:
void checker(int ch, int xpos, int ypos)
{
int flag=0;
struct node *temp,*temp1,*insert_node=NULL;
temp=(struct node *)malloc(sizeof(struct node));
temp=head;
while(temp!=NULL)
{
if(temp->x==xpos && temp->y==ypos)
{
insert_node->c=ch;
insert_node->x=xpos;
insert_node->y=ypos;
if(temp->previous==NULL) //this is for inserting at the first
{
insert_node->next=temp;
head=insert_node;
}
else //this is for inserting in the middle.
{
temp1=temp;
temp=insert_node;
insert_node->next=temp1;
}
flag=1;
break;
}
temp=temp->next;
}
//this one's for the normal insertion and the end of the linked list.
if(flag==0)
characters(ch,xpos,ypos);
}
None of the inserting in the first and middle works. I do not know where it went wrong. Please help me.
temp=(struct node *)malloc(sizeof(struct node));
temp=head;
You are allocating space for a new node, but then you loose the address of this new node assigning temp=head.
The problem is that insert_node is a local variable in your function checker() which is also initialized as NULL. Doing insert_node->c means NULL->c which i'm sure you'll agree with me that is wrong.
Try to dynamically allocate memory for your variables before using them and you should be fine.
insert_node will always be NULL in the code you posted.
Also, you may want to split your code more; start by isolating part of it in a find() function.

Resources