Supplied parameter to the function becomes NULL? - c

I wrote a recursive function to reverse a linked list as follows:
struct node{
int val;
struct node *next;
};
//Global pointer to structure
struct node *start=NULL,*head=NULL;
//*Function to input node*
void create(int data){
struct node *temp;
temp=(struct node *)malloc(sizeof(struct node));
if(start == NULL){
temp->val=data;
temp->next=NULL;
start=temp;
head=temp;
}
else{
temp->val=data;
temp->next=NULL;
head->next=temp;
head=temp;
}
}
*Function to reverse the linked list*
void* rev(struct node *prev,struct node *cur){
if(cur!=NULL){
printf("Works");
rev(cur,cur->next);
cur->next=prev;
}
else{
start=prev;
}
}
And the related code in main is:
main(){
struct node *temp;
temp=start;
/*Code to insert values*/
rev(NULL,temp);
}
Now the code takes input and prints it perfectly, but after I call rev() function the same traversal function prints nothing.
I did run the code on debugger line by line n it gave me the following output:
rev (prev=0x0, cur=0x0)
Also since cur is somehow NULL, the if part of rev() never gets executed and only the else executes once.
When I take input in my create() function I do update start to the first element of the linked list and even in main a print statement proves it is so.
But then why the function rev() always receives input parameters as NULL?
Please comment if any extra information is required.

Specific problems with your code: your main() function lacks sufficient code to test the reversal functionality (e.g. it doesn't create any nodes!); your create() routine really needs a head and tail pointer to work correctly, not the current head and start; your reversal function maintaines the head/start pointer but doesn't handle a tail pointer; you've redundant code in your if and else clauses that can be pulled out of the conditional; you declared rev() a void * instead of simply a void.
I've reworked your code below with addressing the above changes along with some style issues:
#include <stdlib.h>
#include <stdio.h>
struct node {
int value;
struct node *next;
};
// Global pointers to structure
struct node *head = NULL, *tail = NULL;
// Function to add node
void create(int data) {
struct node *temporary = malloc(sizeof(struct node));
temporary->value = data;
temporary->next = NULL;
if (head == NULL) {
head = temporary;
} else {
tail->next = temporary;
}
tail = temporary;
}
// Function to reverse the linked list
void reverse(struct node *previous, struct node *current) {
if (current != NULL) {
reverse(current, current->next);
current->next = previous;
} else {
head = previous;
}
if (previous != NULL) {
tail = previous;
}
}
void display(struct node *temporary) {
while (temporary != NULL) {
printf("%d ", temporary->value);
temporary = temporary->next;
}
printf("\n");
}
// And the related code in main is:
int main() {
/* Code to insert values */
for (int i = 1; i <= 10; i++) {
create(i);
}
display(head);
reverse(NULL, head);
display(head);
create(0);
display(head);
return 0;
}
OUTPUT
> ./a.out
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1 0
>
You should add a routine to free the nodes in the linked list.

Related

Any idea why I’m losing links?

I have started to learn about linked lists, and I have written this code.
It should be a recursive call to create a new link in a linked list in c.
But, if you’ll check the output, you’ll see it’s passing over the middle links.
I don’t know why I’m losing the middle links.
Btw, I do have a destroy function in my code, I just didn’t write it here.
I do have a different version of a working code, I don’t ask for solutions, I’m only asking why this recursive idea doesn’t work.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node {
int data;
struct node *next;
}node;
node *create(node **head, int data)
{
if(!*head) {
*head = malloc(sizeof(node));
assert(*head);
(*head)->data = data;
(*head)->next = NULL;
return *head;
}
node *new = NULL;
new = create(&new,data);
(*head)->next = new;
return *head;
}
void display(node *head)
{
assert(head);
node *current = head;
do
{
printf("%d\t",current->data);
current = current->next;
}while(current);
}
int main()
{
int count = 0, data = 0;
node *head = NULL;
printf("Enter list count:\n");
while(count <= 0){
scanf("%d",&count);
if(count <= 0) printf("\nEnter a valid number:\n");
}
while(count){
scanf("%d",&data);
head = create(&head,data);
count--;
}
printf("\nHere are the elements:\n");
display(head);
return 0;
}
As implemented create() either adds a new node to the tail or iterates to the next linked node. Logic changed to affect that. It's confusing that the first argument is called head to changed it to n. Changed main() to retain the head and made the program non-interactive for ease of testing. Recatored display to use a for() loop:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
node *create(node **n, int data) {
if(!*n) {
*n = malloc(sizeof(**n));
assert(*n);
(*n)->data = data;
(*n)->next = NULL;
return *n;
}
node *n2 = (*n)->next;
(*n)->next = create(&n2, data);
return n2;
}
void display(node *head) {
assert(head);
for(node *c = head; c; c = c->next) {
printf("%d\t", c->data);
}
}
int main() {
node *head = NULL;
node *tail = NULL;
for(int i = 0; i < 10; i++) {
tail = create(&tail, i);
if(!head) head = tail;
}
display(head);
return 0;
}
and it displays:
0 1 2 3 4 5 6 7 8 9
If you compile your code with NDEBUG (some folks do that for production) then your code no longer has any error handling.
Thank you all for your answers. I see the problem now, after “explaining to the duck” a thousand times. In function create(), under the if() block, I assigned (*head)->next = new; without first making it point to the last link, so it’s just over write the next link in every call to the function.
The solution is:
Add a “current” pointer points to the head(to not lose it’s value)
Iterate through the list until we find the last link,
assign current->next the value of new.
Here is the fixed section:
node *new = NULL;
new = create(&new,data);
node *current = *head;
while(current->next) current = current->next;
current->next = new;
return *head;

The display function doesn't execute , the head value keeps getting set to null so the display function keeps printing empty

#include <stdlib.h>
#include <stdio.h>
struct node *create(int num);
void display(void);
//linked list node creation
struct node
{
int data ;
struct node *next;
};
struct node *head = NULL;
struct node *newnode;
struct node *temp;
int main()
{
int num;
printf("enter no of nodes\n");
scanf("%d",&num);
for(int i = 1 ;i<=num;i++)
{enter code here
create(num);
}
display();
return 0 ;
}
// this executes properly
struct node *create(int num)
{
newnode = (struct node *)malloc(sizeof (struct node));
printf("enter data\n");
scanf("%d",&newnode->data);
newnode->next= NULL;
if(head == 0)
{
head=newnode=temp;
}
else
{
temp->next=newnode;
temp= newnode;
}
return head;
}
void display()
{
struct node *temp = head;
if (temp == NULL)
{
printf("empty\n");
}
// the create function works properly but the head keeps getting set to null
//doesn't execute this loop even if the linked list is not empty
else
{
while(temp != NULL)
{
printf("%d-->",temp->data);
temp= temp->next;
}
}
return;
}
Do I need to create a temporary variable everytime I declare a function? Why are the global variables not working? If someone can point out the exact mistake please?
Thanks in advance
Everything in your code was correct. This line was causing issue head=newnode=temp; It should be like shown in snippet below. Because instead of assigning your newly created node's address to head and temp you were assigning temp's initial address.
if(head == 0)
{
head=temp=newnode;
}

Priority queue not inserting element in ascending order

This is the code of priority queue using linked list
i have two doubts in this code
1) This code is part of my insert function
if((*addofhead)->priority <= newnode->priority ){
struct node* temp=*addofhead;
while(temp->next!=NULL&&temp->priority <newnode->priority ){
temp=temp->next;
}
newnode->next=temp->next;
temp->next=newnode;
return;
}
why we can not do temp!=NULL in while loop instead of temp->next!=NULL because temp!=NULL will also make loop exit in one more iteration but it is crashing what is the reason of crashing
2)I want to make a priority queue such that the element which has least priority
should be removed first and elements which has same priority then the element will be removed first which was added first
input part from main function
insert(&head,3,5);
insert(&head,2,2);
insert(&head,1,1);
insert(&head,7,1);
insert(&head,11,1);
insert(&head,8,5);
insert(&head,9,5);
I am getting output for this 1 2 11 7 3 8 9 but its output should be 1 7 11 2 3 8 9
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
int priority;
struct node* next;
};
struct node* getnewnode(int data,int priority){
struct node* newnode=malloc(sizeof(struct node));
newnode->data=data;
newnode->next=NULL;
newnode->priority=priority;
return newnode;
}
void insert(struct node** addofhead,int data,int priority){
struct node* newnode=getnewnode(data,priority);
if(*addofhead==NULL){
*addofhead=newnode;
printf("head in insert is %d",*addofhead);
return;
}
if((*addofhead)->priority > newnode->priority){
newnode->next=*addofhead;
*addofhead=newnode;
return;
}
if((*addofhead)->priority <= newnode->priority ){
struct node* temp=*addofhead;
while(temp->next!=NULL&&temp->priority <newnode->priority ){
temp=temp->next;
}
newnode->next=temp->next;
temp->next=newnode;
return;
}
}
int removee(struct node** head){
if(*head==NULL)
return -1;
int temp=(*head)->data;
*head=(*head)->next;
return temp;
}
int main(){
struct node* head=NULL;
insert(&head,3,5); /// 3
insert(&head,2,2); /// 2,3
insert(&head,1,1); /// 1,2,3
insert(&head,7,1);
insert(&head,11,1);
insert(&head,8,5); /// 1,7,2,3
insert(&head,9,5);
struct node* temp=head;
while(temp)
{
printf(" %d ",temp->data);
temp=temp->next;
}
printf("\n head in main after insertion is %d",head);
}
why we can not do temp!=NULL in while loop instead of temp->next!=NULL (?)
Because the line after the loop has temp->next; #Jonathan Leffler.
The usual goal on marching down a linked list for insertion is to know the pointer of the previous node so its .next member may be updated.
Code has 2 functional problems
Comparing wrong priorities
// while(temp->next!=NULL&&temp->priority <newnode->priority ){
while(temp->next!=NULL&&temp->next->priority <newnode->priority ){
// ^^^^^^
Wrong compare when ==
// while(temp->next!=NULL&&temp->next->priority <newnode->priority ){
while(temp->next!=NULL&&temp->next->priority <= newnode->priority ){
// ^^^^^^ ^^
Also use %p to print a void *, not "%d" to print a pointer.
// printf("head in insert is %d",*addofhead);
printf("head in insert is %p",(void *) (*addofhead));
What was very useful to advance this was to create a helper function to print the data. It was then easy to call it after each insertion to narrow the issues.
void pq(const struct node* p) {
while (p) {
printf("(data %d,pri %d) ", p->data, p->priority);
p = p->next;
}
puts("");
}
I found OP's insert() overly complex. See #wildplasser.

Infinite loop in insertion in linked list

While inserting node at end in linked list ,my code is running in infinite loop.
IDE Used-Eclipse
64 bit OS
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head;
node *ptr1;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
//To insert the data in linked list
void insert(int x)
{
node *ptr;
ptr1=head;
ptr=(node*)malloc(sizeof(node));
ptr->info=x;
if(head==NULL)
{
ptr->next=head;
head=ptr;
}
else
{
ptr1->next=NULL;
ptr1=ptr;
}
}
//To print the details of list
//Unable to figure out this function
void show()
{
while(ptr1->next!=NULL)
{
printf("%d\n",ptr1->info);
ptr1=ptr1->next;
}
}
The ptr1 is set to head each time your code enters the insert function then setting it to ptr in the else subsection but nothing pointing to any previous items.
Here is an example in case you need one.
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head = NULL;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
void insert(int x)
{
node *ptr = (node*)malloc(sizeof(node));
ptr->info=x;
ptr->next=head; /* this will always add the new entry at the beginning of the list all you need it to initialize the head to NULL*/
head = ptr; /* move the head so that it points to the newly created list element */
}
void show()
{
node *ptr1 = head;
printf("%d\n",ptr1->info); /* print the head */
while(ptr1->next!=NULL) /* now walk the list remember it first looks if the next pointer in the list is null first then it jumps on next element in case it is not*/
{
ptr1=ptr1->next;
printf("%d\n",ptr1->info);
}
}
Remember to create a function to free up the list elements before exiting the main.
Your two functions can be simplified. A singly linked list is very easy to implement. I would also improve the functions by taking the list pointer as an argument, and in the case of insert() return the new head of the list: but get it working first! Note there is no reason or need to declare global variables when their only use is local to a function.
// insert new node at head of the list
void insert(int x) {
node *ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = head; // append existing list
head = ptr; // new head of list
}
// show the linked list
void show() {
node *ptr = head; // start at head of list
while (ptr != NULL) {
printf("%d\n", ptr->info);
ptr = ptr->next; // follow the link chain
}
}
EDIT here is code to add to the tail of a linked list
// insert new node at tail of the list
void insert2(int x) {
node *tail = head;
node **last = &head;
node *ptr;
while (tail) {
last = &tail->next;
tail = tail->next;
}
ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = NULL;
*last = ptr;
}

Why does my link list have the wrong data?

When printing out my linked list, what is displayed is not what I assumed it to be. How do I get the right output?
struct node{
int data;
struct node *next;
};
struct node *newNode(int data){
struct node *new_node=(struct node *) malloc(sizeof(struct node));
new_node->data=data;
new_node->next=NULL;
return new_node;
}
void push(struct node*** head, int data){
struct node* new_node=newNode(data);
new_node->next=(**head);
(**head)=new_node;
}
void create(struct node **number, char num[]){
int x=0;
while(x<strlen(num)){
int d=(int)(num[x]);
push(&number, d);
x++;
}
}
void printList(struct node *number){
while(number!=NULL){
printf("%d", number->data);
number=number->next;
}
printf("\n");
}
int main (void){
struct node *first;
char num1[10];
scanf("%s", num1);
create(&first, num1);
printList(first);
return 0;
}
Examples
Input : 1
Expected Output: 1
Actual Output : 49
Input : 12345
Expected Output: 12345
Actual Output : 5352515049
I think it is printing where the value is stored, not the value itself.
Correct me on that if that's wrong. Anyways how do I get the expected output I want.
The problem is that you are reading ascii values, and then trying to print integers, and since you need to store integers and not the ascii values all you need is a simple mathematical operation, i.e. subtract the ascii value of the digit '0', so to convert the ascii value of a digit to it's integer value all you need is
integer = ascii - '0';
here I fixed your code, because you were appending the value to the head of the list instead of it's tail
#include <stdlib.h>
#include <stdio.h>
struct node{
int data;
struct node *next;
};
struct node *newNode(int data)
{
struct node *new_node;
new_node = malloc(sizeof(struct node));
if (new_node == NULL) /* always check that malloc succeeded */
return NULL;
new_node->data = data;
new_node->next = NULL;
return new_node;
}
struct node *push(struct node *tail, int data)
{
struct node *new_node;
new_node = newNode(data);
if (tail != NULL)
return tail->next = new_node;
return new_node;
}
struct node *create(char *numbers)
{
size_t i;
struct node *head;
struct node *tail;
i = 0;
head = NULL;
tail = NULL;
/* since strings are 'nul' terminated, you just need to loop,
* until you find the 'nul' byte, strlen() expects that byte
* anyway.
*/
while (numbers[i] != '\0')
{
tail = push(tail, numbers[i++] - '0');
if (head == NULL)
head = tail;
}
return head;
}
void printList(struct node *number)
{
while (number != NULL)
{
printf("%d", number->data);
number = number->next;
}
printf("\n");
}
void freeList(struct node *number)
{
while (number != NULL)
{
struct node *last;
last = number;
number = number->next;
free(last);
}
}
int main(void)
{
struct node *first;
char numbers[10];
/* '%9s' prevents buffer overflow */
if (scanf("%9s", numbers) != 1)
return -1;
first = create(numbers);
printList(first);
freeList(first);
return 0;
}
You have a linked list which ends up in reverse order, and this is why your second example comes out in reverse order. If you print the linked list like this:
printf("%d ", number->data);
with a space, it would be clearer what is happening, output is ASCII values
53 52 51 50 49
But you are also confusing character values with numeric values. If you correct this,
printf("%c ", number->data);
you will get your original input characters in reverse order.
5 4 3 2 1

Resources