using while in recursive function - c

to display a linked list, I am using a recursive function. which was running infinite loop thanks to while loop.
when replaced with "if" the program worked without any issues.
looking for expert opinion on usage of
while
inside a recursive function.
recursive function with while
int display(node *curr){
if((curr->next != NULL) ){ //<--replace "if" with "while" and it runs infinite loop
printf("%d :: ",curr->data);
display(curr->next);
}
return 0;
}
complete code with create and display function
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node node;
int create(node *head);
int display(node *head);
int main(int argc, char *argv[]){
int ch,n=0;
node *head,*tail,*current;
head=(node*)malloc(sizeof(node));
create(head);
printf("\n");
display(head);
return 0;
}
int create(node *curr){
int data;
node *next;
printf("Enter the Data Value (Enter -1 to Finish): ");
scanf("%d",&data);
curr->data=data;
if(data == -1)
{
curr->next=NULL;
//return curr;
}
else
{
curr->next=(node*)malloc(sizeof(node));
create(curr->next);
}
return 0; }
int display(node *curr){
if((curr->next != NULL) ){
printf("%d :: ",curr->data);
display(curr->next);
}
return 0; }

The reason why you cannot use the while(curr->next != NULL) loop to index through and print the list is because for each call of the function display(), the value of curr->next is constant. This seems like it will successfully print the data in your linked list, and then infnitely print the second to last data point, as the comparison for the last data point will continually fail.
as suggested by Ritwick Dey, using
int display(node *curr)
{
while (curr)
{
printf("%d",curr->data);
curr = curr->next;
}
}
should work for you; by changing the pointer of the current node, you modify the conditional of the while loop every iteration. a value of NULL will cause this check to fail, so you can print the final data point without issue. this implementation has the added benefit of avoiding the cost of the recursive function call.

Though the question is not fully clear, I think you are asking why the code is working after changing the 'while' statement to 'if'. The explanation is below:
1.)You are not advancing your next pointer.
2.)Let's assume you have advanced your next pointer even then your code will run infinitely.
A simple dry run should be enough for this:
Let's take an example suppose your Singly link list of positive integers looks like this:
8-->9-->7-->NULL
Then following will be your recursion tree which illustrates on which condition your code is running infinitely.
display(8)
while(8->next)->display(9)
        while(9->next)->display(7)
               while(7->next)->display(NULL)--return
After returning from display(NULL) this will run infinitely for this case: while(7->next)---->display(NULL) and it will continue to loop around the same.
The correct function to display the link list is already pointed out in the Ritwick's answer.

int display(node *curr)
{
while (curr)
{
printf("%d",curr->data);
curr = curr->next;
}
}
Simple......

You get an infinite loop because you never advance the in the list, that's: l = l->next(); so, you never reach null

Related

Can't seem to ever get the print function in linked list in c

cant print the linked list, it gets stuck in an infinite loop cant understand where i'm going wrong.
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
node *head = NULL;
void print(node *head){
node *temp = head;
while(temp!=NULL);
{
printf("%d => ",temp->data);
temp = temp->next;
}
printf("NULL");
}
node *clist(int n){
node *temp = NULL;
node *p = NULL;
int i;
for(i=0;i<n;i++)
{
temp = (node*)malloc(sizeof(node));
printf("Enter the elements of the list.\n");
scanf("%d",&temp->data);
}
if(head!=NULL)
{
while(p->next!=NULL)
p=p->next; //shifting p here node by node
p->next = temp; //last node which was just created
}
else
{
head = temp;
}
return head;
}
node *binsert(int x){
node *temp = NULL;
node *p = NULL;
temp = (node*)malloc(sizeof(node));
if(head!=NULL)
{
temp->next = head;
temp = head;
}
else
{
p = head = temp;
}
return head;
}
int main ()
{
int a, s, i, n,f;
printf("Choose an option : \n1.Create a list.\n2.Exit.\n");
scanf("%d",&s);
switch(s)
{
case 1:
printf("Very Well! Input the number of nodes\n");
scanf("%d",&n);
head = clist(n);
printf("Link List created successfully.\n");
print(head);
break;
default:
exit (0);
}
printf("Choose the operation you want to perform on the linked list:\n1.Add an element to the beginning.\n2.Add an element to the end.\n3.Add an element at a a particular position.\n");
scanf("%d",&a);
switch(a)
{
case 1:
printf("Enter the element you want to insert at the beginning.\n");
scanf("%d",&f);
binsert(f);
printf("Inserted Successfully.\n");
print(head);
break;
case 2:
printf("Error E162B");
}
return 0;
}
I tried changing the head to a global variable. re-wrote the code 7 times. please help.
First:
for(i=0;i<n;i++)
{
temp = (node*)malloc(sizeof(node));
printf("Enter the elements of the list.\n");
scanf("%d",&temp->data);
}
This loop repeats several times so that the user can enter the elements of the list. But it never adds any of the nodes to the linked list. Each iteration of the loop changes temp to point to a newly-allocated node but doesn't add the nodes to the linked list.
Second:
while(temp!=NULL);
This is an endless loop right here. If temp is not NULL, it's not changed anywhere in the loop, so it will never become NULL. You don't want that semicolon there.
Third:
node *head = NULL;
void print(node *head){
node *temp = head;
Don't do this to yourself. You have a global variable called head and you have a parameter called head. When you do node *temp = head; how obvious is it which head that's referring to. Don't give two variables the same name if their scope overlaps.
Fourth:
if(head!=NULL)
{
temp->next = head;
temp = head; // **** here
}
else
{
p = head = temp;
}
return head;
What's the point of temp = head;? The value of temp isn't accessed anywhere. So that can't be right.
Lastly:
I think you didn't ask the right question though. You asked us to explain where you're going wrong, and I've done that. But I don't think that's what you actually need. Maybe you need help developing the algorithm to solve the problem? Perhaps ask a new question describing what you think the algorithm should be (just in words, no need to use code) and ask for help fixing the algorithm.
And, to be blunt, the number of mistakes suggests that you are attempting a task that is significantly beyond your knowledge. This is frustrating and not a good way to learn programming. You should seriously consider attempting simpler tasks first.
You may have stripped it out to keep the question simple, but your real code should contain lots of extra checking and logging to help you understand it. Log when you enter a function. Log each decision the function makes. Log what functions return. That will help you determine where the program's actual operation is deviating from you think it should be doing. Or, if you prefer, learn to use your platform's debugging facilities. That way, you won't be making random changes and hoping that they make everything work but will instead know where the code is first going awry and be able to fix one thing at a time confident that you are not breaking things that were working.

Using a while loop to check the content of struct

I'm trying to append a node to a linked list however, when I use a while loop to check if the "link" is set to NULL, the loop is being executed when it shouldn't.
It is as if the "cursor->link" was not set to NULL and the code inside the while loop is being executed, I put the print statement there just to test it and it is being executed even though "cursor->link" is set to NULL. The create function returns a "node*".
EDIT - I apologize guys, I posted this question late at night and I guess I might not have been in the best shape to express myself properly. Plus I'm still a bit confused about how to handle and work with Linked Listing (as my code probably shows). I've been given a template to work with (as in the functions append and display were preset and I've to work with them as is). The compiler did not set off any warnings with the code as is. However the program still crashes in the append function around the While loop.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node {
int data;
struct node * link;
} node;
node* create(int data,node* link) {
node* newNode = (node*)malloc(sizeof(node));
newNode->data = data;
newNode->link = link;
return newNode;
}
void append ( node **, int ) ;
void display ( node * ) ;
int main() {
node *p ;
p=NULL;
int n;
char ch[10];
do {
printf("Enter the value\n");
scanf("%d",&n);
append(&p,n);
printf("Do you want to add another node? Type Yes/No\n");
scanf("%s",ch);
}while(!strcmp(ch,"Yes"));
printf("The elements in the linked list are");
display(p);
printf("\n");
return 0;
}
/* adds a node at the end of a linked list */
void append ( node **q, int num ){
node *cursor;
if (*q == NULL) {
*q = create(num, NULL);
node *cursor = *q;
}
while(cursor->link != NULL) {
printf("1\n");
cursor = cursor->link;
}
node* newNode = create(num, NULL);
cursor->link = newNode;
}
void display ( node *q ){
node *cursor = q;
while(cursor->link != NULL) {
printf(" %d", q->data);
cursor = cursor->link;
}
printf(" %d", cursor->data);
}
As Ry mentioned, problem is with the cursor you are using in while loop, it's never initialized. Instead you are creating a new variable with the same name when *q is null. I see one more problem in your code, when list is empty you are adding new node twice. First in null check condition and then after while loop.
To fix move this line
"node *cursor = *q"
outside if condition and add a return instead. Also remove this line
"node *cursor"
Note:: I am assuming your create method has no issue.

linkedlist: count=count->next gives segmentation fault

#include<stdio.h>
#include<malloc.h>
typedef struct nde{
int data;
struct nde *next;
}node,*pnode;
void inst_beg(node *,int);
void inst_end(node *,int);
void inst_any(node *,int,int);
int del_begin(node *);
int del_end(node *);
int del_any(node*,int);
void display(node *);
main()
{
pnode head= (node *)malloc(1*sizeof(node));
head->data=0;
head->next=NULL;
inst_any(head,1,1);
inst_any(head,2,2);
// inst_any(head,3,3);
display(head);
}
void inst_any(node *head,int pos, int data){
pnode nd=(node *)malloc(1*sizeof(node));
nd->data=data;
//pnode count=(node *)malloc(1*sizeof(node));
pnode count;
count=head;
printf("head: %p",head);
printf("count: %p",count);
int i=0;
while(i<pos-1){
count=count->next; //Problem is here for inst_any(phead,2,2)
}
nd->next=count->next;
count->next=nd;
//printf("done");
}
void display(node * head){
pnode count=head;
while(count->next!=NULL){
printf("%d",count->data);
count=count->next;
}
}
Value of count is becoming null inside loop so we are not able to deference it when it is coming second time when inst_any(head,2,2) is being called. Checked with gdb that first time count is successfully being pointed to head. And same is happening for second time also. After count=head it is giving correct value for second time. Dont know what is happening after that. Why when its coming inside the loop count's value is becoming zero.
Look at this code:
while(i<pos-1){
count=count->next; //Problem is here for inst_any(phead,2,2)
}
That's the whole loop. So either your condition i<pos-1 is false right away .... or it is true and stays true, as you never modify i nor pos in your loop.
In the latter case, you walk a linked list. Eventually, you'll find the end (count->next is NULL) and still assign this NULL to count. In the next iteration, you try to dereference NULL to access ->next. Trying to dereference NULL is undefined behavior, a segmentation fault is a typical consequence.
Go and rethink your program (e.g., check whether count->next is still not NULL in your loop condition).
I have corrected your code with comments below. Please read my comments in the codes else you can not realize your mistakes. Hope this will help you.
typedef struct nde{
int data;
struct nde *next;
}node,*pnode;
void inst_beg(node *,int);
void inst_end(node *,int);
void inst_any(node *,int,int);
int del_begin(node *);
int del_end(node *);
int del_any(node*,int);
void display(node *);
void main()
{
pnode head= (node *)malloc(sizeof(node)); //No need to multiply by one
head->data=0;
head->next=NULL;
inst_any(head,1,1);
inst_any(head,2,2);
inst_any(head,3,3);
display(head);
inst_any(head,4,4); //I am adding this statement so that you can better understand where it going to be inserted
display(head);
inst_any(head,7,7);
}
void inst_any(node *head,int pos, int data){
pnode nd=(node *)malloc(sizeof(node));
nd->data=data;
//pnode count=(node *)malloc(1*sizeof(node));
pnode count;
count=head;
printf("head: %p\n",head);
printf("count: %p\n",count);
int i=0;
while(i < (pos-1)){
if(count == NULL){
printf("No position available for request pos =%d\n", pos);
return;//This condition is important. If your position is not exist in the list and count reached the end of the list just return with a error message
}
count=count->next; //Problem is here for inst_any(phead,2,2)
i++;//you must increment i
}
nd->next=count->next;
count->next=nd;//Here count must not be null, else it will create Segmentation fault. Therefore inside from while loop above we have checked whether it is null or not. If null return from this method.
//printf("done\n");
}
void display(node * head){
pnode count=head;
while(count!=NULL){//You have to correct it to print last node of the list
printf("%d\n",count->data);
count=count->next;
}
}
the posted code for the function: inst_any() initializes the data field, but fails to initialize the next field.
Suggest:
nd->data=data;
nd->next = NULL;
Then this loop:
while(i<pos-1){
count=count->next; //Problem is here for inst_any(phead,2,2)
}
fails to update the counter i so the loop never exits. Also, when the linked list does not contain enough entries this loop will run right off the end of the list. So the loop also needs to be checking that the count->next is not NULL.

How to Reverse singly linked list properly in C? [duplicate]

This question already has answers here:
How to reverse a singly linked list using only two pointers?
(36 answers)
Closed 7 years ago.
well im starting with C and i've been asked to do a linked list that has random integers in its nodes data, they must be in ascendant order and later i have to reverse their order with a function. The problem im having is that in my reverse output, im only getting the first number and its not even reversed.
#include <stdio.h>
#include <stdlib.h>
int N;
typedef struct node{
int num;
struct node *next;
}nodes;
int first_node(nodes *head){
if(head == NULL){
printf("Error");
}
else{
head -> num= rand();
head->next=NULL;
}
}
int second_node(nodes *head){
nodes *uno=malloc(sizeof(nodes));
if(uno == NULL){
printf("Error");
}
else{
uno->num = rand();
uno->next = NULL;
if( uno->num>head->num){
head->next=uno;
}
else{
head= uno->next;
}
}
}
int insert_node(nodes *head){
nodes *dos=malloc(sizeof(nodes));
if(dos == NULL){
printf("Error");
}
else{
dos->num = rand();
dos->next = NULL;
nodes *current = head;
while(current!= NULL){
if(current->num<dos->num && current->next==NULL){
current->next = dos;
return;
}
else if (current->num<dos->num && current->next->num>dos->num){
dos->next=current->next;
current->next=dos;
return;
}
else if(head->num>dos->num){
dos->next=head;
head=dos;
}
current=current->next;
}
}}
void printnodes(nodes *head){
nodes *current = head;
while (current != NULL){
printf("%d\n",current->num);
current = current ->next;
}
}
void reverse(nodes *head)
{
nodes *a=head->next;
if(a!=NULL)
{
nodes *b=a->next;
a->next=head;
head->next=NULL;
head=a;
if(b!=NULL)
{
while(b!=NULL)
{
a=b;
b=b->next;
a->next=head;
head=a;
}
a->next=head;
head=a;
}
}
}
int main(){
printf("Insert the number of nodes u want to create:");
scanf("%d", &N );
nodes *head =malloc(sizeof(nodes));
int i =3;
if(N==1){
first_node(head);
}
else if (N ==2){
first_node(head);
second_node(head);
}
else if (N>2){
first_node(head);
second_node(head);
while(i<=N){
insert_node(head);
i++;
}
}
printnodes(head);
printf("\n\n Reversed \n\n");
reverse(head);
printnodes(head);
return 0;
}
The output im getting creating 5 nodes is :
In order:
41
3445
3890
8709
16777
Reversed :
41
how can i fix this?, thanks and sorry for the bad english
There are two very obvious problems in your code:
The first is that you assign to a local variable, expecting that assignment to be reflected once the function returns. I'm talking about your assignment to head in most functions. The problem here is that when you pass an argument to a function. it's passed by value, meaning it's copied and what you have in the function you call is just a copy or the original value. And as you should know, changing a copy will not change the original.
The second problem that I see at a quick glance is in the second_node function, where you first do
uno->next = NULL;
and potentially followed by
head= uno->next;
This will assign NULL to head.
The first problem is easy to solve, by emulating something called pass by reference. I say emulating, as C only have pass by value. You can emulate pass by reference in C using pointer, which means that to pass a pointer "by reference" in C, you have to pass a pointer to the pointer, like
int second_node(nodes **head){
...
}
You then call it using the address-of operator:
second_node(&head);
Then in second_node you use the dereference operator * to access the "original" head pointer, like
*head = uno->next;
Writing the above I noticed a third problem, and that is that you declare some functions as returning an int, but you don't actually return anything from the functions. Thankfully it seems that you don't use the returned value anywhere, but it's still is undefined behavior to not return a value in a function that should return a value. If you should not return a value from a function it must be declared as returning void:
void second_node(nodes **head){...}

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.

Resources