I am trying to add a new node to the linked list. Online tutorials(http://www.geeksforgeeks.org/linked-list-set-2-inserting-a-node/) uses a pointer to a pointer and I am not able to understand how it works. So I decided to write my own code but I am having a problem with the push() function. Here is the code.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node* next;
};
void print_list(struct node *head_ptr)
{
while(head_ptr!=NULL)
{
printf("%d->",head_ptr->data);
head_ptr = head_ptr->next;
}
}
void push(struct node *head_ptr, int data_val)
{
struct node *new_node = (struct node*)malloc(sizeof(struct node));
new_node -> data = data_val;
new_node->next = head_ptr;
head_ptr = new_node;
}
int main()
{
struct node *head = (struct node*)malloc(sizeof(struct node));
struct node *second = (struct node*)malloc(sizeof(struct node));
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;
print_list(head);
push(head,0);
printf("\n");
print_list(head);
return 0;
}
It compiles without error. However, the expected node with value 0 does not get inserted in the beginning of my linked list.
Current Output
1->2->3->
Expected Output
0->1->2->3->
Please help me get the required output without using pointer to a pointer in push() function. Also, share a link to a source which has a good explanation of pointer to a pointer and it relates to the linked list.
You are doing it wrong way.
The thing is when you pass head in push a copy of it is passed to push. The content of them are same. Now what you are doing?
Creating new node. Then you make changes to that copy of the variable. Then the function ends and the lifetime of that variable ends and so is the access to the allocated memory (creating memory leak). And the original head in main() still is same. That's why it prints 1-2-3.
Solution-1
head = push(head,0);
And
struct node* push(struct node *head_ptr, int data_val)
{
struct node *new_node = (struct node*)malloc(sizeof(struct node));
new_node -> data = data_val;
new_node->next = head_ptr;
head_ptr = new_node;
return head_ptr;
}
Solution-2
void push(struct node **head_ptr, int data_val)
{
struct node *new_node = (struct node*)malloc(sizeof(struct node));
new_node -> data = data_val;
new_node->next = *head_ptr;
*head_ptr = new_node;
}
And call it like
push(&head,0);
Explanation of solution-2
Now here you pass &head to the function meaning you pass the address of it to the function push(). Now in push() you have a variable named head which is a contains the address of the head. Now by dereferencing it you are basically the head of main()and any changes you make to *head will retain because you are changing to the actual variable, whose address was passed.
Explanation of solution-1
Here we don't pass the address. But rather we pass the content of the head variable of main(). Now you allocate memory and you get it's address. You make changes to it. And then you put in the next the address of the head and then you point head to the newnode. And you may ask so it changes the origibal head? Nope. that's why we return it and we store it in the originbal head in main().
Note:
The dynamically allocated memory is have lifetime beyond the scope of the function. That's why you can return it's address and there will not be any problem.
You don't need to cast the return type of malloc. That's not needed.
struct node *new_node = malloc(sizeof(struct node));
Or
more clearly
struct node *new_node = malloc(sizeof *new_node));
Also check the return value of malloc.
Free the dynamically allocated memory when you are done working with it.
Where is logical error in the given code?
In C function arguments are always "call by value".
A function can change the function arguments but this has no impact on the argument in the calling function. Example:
void x(int a)
{
a = a + 10;
printf("%d\n", a);
}
void y(void)
{
int b = 9;
x(b); /* Line 1 */
x(123); /* Line 2 */
}
The line a = a + 10; will have the effect that 19 and 133 are printed instead of 9 and 123.
However it will not have the effect that b is changed to 19 in "line 1"; for "line 2" it should be clear that such an effect is even impossible.
In your code the line head_ptr = ... has the same effect.
Please help me get the required output ...
As the C language does not provide real "call by reference" arguments you use pointers to variables as "call by value" arguments to simulate "call by reference" arguments:
void x(int *a)
{
(*a) = (*a) + 10;
printf("%d\n", *a);
}
...
x(&b);
Or, in your example:
/* Note the two "**"s in this line: */
void push(struct node **head_ptr, int data_val)
{
...
*head_ptr = new_node; /* Note the "*" */
}
...
push(&head,0);
Of course you can only pass variables to functions this way.
Everything in C is passed by value. Even the pointers
So
I have two pointers
void swap(char* first, char* second)
{
//take temp var and swap
}
main(){
char *first, *second;
first = 0x1;
second = 0x2;
printf("%x, %x", first, second);
swap(first, second);
printf("%x, %x", first, second);
}
this code will not swap the values, since in swap(), the locally created values on stack are being swapped.
Realize that pointers are behaving just like another normal variables there.
Yes but if you dereference them you can swap the values pointed by the pointers inside the swap().
Catch is: head you passed is passed by value, the push() function does its job but assignment to head is done LOCALLY.
***SOLVED***
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node* next;
};
void print_list(struct node *head_ptr)
{
while(head_ptr!=NULL)
{
printf("%d->",head_ptr->data);
head_ptr = head_ptr->next;
}
}
void push(struct node *head_ptr, int data_val, ***struct node *new_node***)
{
new_node -> data = data_val;
new_node->next = head_ptr;
head_ptr = new_node;
}
int main()
{
struct node *head = (struct node*)malloc(sizeof(struct node));
struct node *second = (struct node*)malloc(sizeof(struct node));
struct node *third = (struct node*)malloc(sizeof(struct node));
***struct node *new_node = (struct node*)malloc(sizeof(struct node));***
head -> data = 1;
head -> next = second;
second -> data = 2;
second -> next = third;
third -> data = 3;
third -> next = NULL;
print_list(head);
push(head,0,new_node);
printf("\n");
print_list(***new_node***);
return 0;
}
Related
I am a beginner in data structure and I recently wrote a code to insert a new node at the beginning of a linked list using functions but when I run it the inserted node doesn't get printed, please help me verify the error in my code and correct it
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
void
traversal(struct Node *ptr)
{
while (ptr != NULL) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
void
insert_first(struct Node *head, int data)
{
struct Node *ptr = (struct Node *) malloc(sizeof(struct Node));
ptr->data = data;
ptr->next = head;
head = ptr;
}
int
main()
{
struct Node *head;
struct Node *second;
struct Node *third;
struct Node *fourth;
head = (struct Node *) malloc(sizeof(struct Node));
second = (struct Node *) malloc(sizeof(struct Node));
third = (struct Node *) malloc(sizeof(struct Node));
fourth = (struct Node *) malloc(sizeof(struct Node));
head->data = 10;
head->next = second;
second->data = 20;
second->next = third;
third->data = 30;
third->next = fourth;
fourth->data = 40;
fourth->next = NULL;
traversal(head);
insert_first(head, 0);
printf("\n");
traversal(head);
return 0;
}
insert_first() function parameter head is a local variable of insert_first() function. So, the statement head = ptr; will make changes in local variable only. These changes will not reflect in the pointer you have passed as first argument to insert_first() function.
As stated in one of the comments that you can return the updated value of head of list and assign that value to original head pointer of list.
Another way could be to pass the address of head pointer of list to insert_first() function (in case, if you want to keep the void as return type of insert_first() function).
For this, you have to changes the type of head parameter of insert_first() function from struct Node * to struct Node ** (double pointer) and pass the address of head (i.e. &head) to insert_first() function. Dereferencing head parameter of insert_first() function will give you the original pointer whose address you have passed and then you can make it point to some other address.
Implementation:
void
insert_first(struct Node **head, int data)
{
struct Node *ptr = (struct Node *) malloc(sizeof(struct Node));
ptr->data = data;
ptr->next = *head;
*head = ptr;
}
and call it like this
insert_first(&head, 0);
^^^
A suggestion:
Follow good programming practise - always check the malloc() return.
I am learning about linked lists, and I want to know if it is okay to pass by address operator or by pointer in the parameter for the given function:
void Push(struct Node **head_ref, int data)
{
struct Node *new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void Push(struct Node *&head_ref, int data)
{
struct Node *new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = data;
new_node->next = head_ref;
head_ref = new_node;
}
struct Node *&head_ref is not valid C. It's how you would declare a reference parameter(a reference to pointer in this case) in C++.
So only the first version is valid in C.
When you call the function, you use the address operator with your variable.
struct Node *head = NULL;
Push(&head, 1);
Push(&head, 2);
In C, it is only passed by value.
Ex in C:
int a;
int *p = &a;
foo(&p); //address of pointer(also a value) is passed to access "int a"
In C++, it is actual pass by reference:
Ex in c++:
#include <iostream>
void foo(int& x){
x = 0; //changes a value to 0
}
int main()
{
int a = 5;
foo(a);
std::cout<<a<<std::endl; //prints 0
return 0;
}
also please have a look at
What exactly is the difference between "pass by reference" in C and in C++?
I am new to C programming. I am trying to implement Linked list by myself. I am encountering problem with pointers
I have function
void Insert(Node* head, int x)
to insert node at the beginning of Linked list. The problem is that when I insert the very first node and Node *head is NULL, the function Insert is not able to change the pointer address of null pointer to the newly created node. It seems as if the Node *head is passed by value and not by reference.
Code is provided below. In order to debug how address is changed throughout the execution, I used printf function.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
int main() {
Node *head = (Node*) malloc(sizeof(Node));
head = NULL;
printf("head in main(): %d\n", head); // For example: 100
Insert(head, 25);
return 0;
}
void Insert(Node *head, int x) {
Node *temp = (Node*) malloc(sizeof(Node));
temp->data = x;
temp->next = head;
printf("temp->next address: %d\n", temp->next); // also 100
head = temp;
printf("%d\n", head); // not 100, something else i.e 200
}
It seems as if the Node *head is passed by value and not by reference.
That is exactly right -- in C every parameter is always passed by value. The pointer is a value, and that value is passed by value, and the call
Insert(head, 25);
can never change the value of the variable named head. It reads the value of the variable (this value is a null pointer), gives that value to the function and never touches the variable head again no matter what the function does.
(Note that in your program you have two variables that are both named head -- one in main() and the other in Insert(). The variable in Insert() silently disappears when the function returns; nothing will automatically try to copy its value to the similarly-named variable in main()).
If you want to (conceptually) pass head by reference, you need to actually pass a pointer to it -- that is, in this case, a pointer to a pointer! You'd need to declare your function as
void Insert(Node **head, int x) { ... }
and call it as
Insert(&head, 25);
Then the actual parameter is a pointer to the variable head which gives the function a chance to update that variable, if you deference the parameter where appropriate:
// ...
temp->next = *head;
// ...
*head = temp;
// ...
Pass a pointer to a pointer to head. That way, you can set head to null.
void Insert(Node **head, int x) {
...
if (*head == NULL) {
*head = temp;
}
else {
...
*head->next = temp;
}
}
Usage:
Node *head = NULL;
Insert(&head, 10);
Having three answers suggesting the same I would like to offer an alternative:
Instead of passing a Node ** to Insert() you could instead have it return the new head, thus:
Node *Insert( Node *head, int x )
{
... your code ...
return head;
}
and if you call it by
head = Insert( head, 24 );
That is neither better nor worse then the other solution so you my do whatever you prefer
There are number of issues here.
1. Your printf statements need to be corrected.
2. To insert function you can pass double pointer.
3. Inside main function, you need not to do Node *head = (Node*) malloc(sizeof(Node));
I have modified your code as shown below. You can try running it and co-relate above points.
typedef struct Node {
int data;
struct Node *next;
} Node;
void Insert(Node **head, int x);
void Insert(Node **head, int x) {
Node *temp = (Node*) malloc(sizeof(Node));
temp->data = x;
temp->next = *head;
printf("temp->next address: %d\n", temp->data); // also 100
*head = temp;
printf("%d\n", (*head)->data); // not 100, something else i.e 200
}
int main() {
Node *head = NULL;
head = NULL;
Insert(&head, 25);
printf("head in main(): %d\n", head->data); // For example: 100
return 0;
}
I am creating a list with 3 elements but when I print the list , it shows an extra zero element.I can't figure where this comes from.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int data;
struct node *next;
} node;
void Push(struct node **head, int data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode-> data = data;
newNode-> next = *head;
*head = newNode;
}
void createList(struct node **head)
{
Push(head, 1);
Push(head, 2);
Push(head, 3);
}
void printList(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d \n", ptr-> data);
ptr = ptr-> next;
}
return;
}
int main() {
struct node *head = NULL;
head = (struct node*) malloc(sizeof(struct node));
createList(&head);
printList(head);
printf("\n");
return 0;
}
Output:
3
2
1
0
It's actually displaying an indeterminate value. Because right here:
head = (struct node*) malloc(sizeof(struct node));
Is where you create the first real node, which everything is inserted before. You are (un)lucky the run-time is zeroing out the memory for you. Because that's the only thing stopping you from accessing some random address. In general, the content of the memory returned from malloc is indeterminate.
Remove that line and you'll see only the items added by createList. Plus your program will be with well defined behavior.
You have four nodes in your list: the original that you malloc in "main()” plus the three added via "Push" in "createList". Presumably the data in the extra one is zero because you haven’t set it in main (although I’d expect it to be gibberish since it’s allocated memory but not cleared).
I have declared a global pointer ptr and want that it should point to current node during different function call.
This is a sample code where I am creating a new node in fun1 and inserting in link list. In func2 I want to update the other members of newNode in linklist with a different value.
Currently I am traversing the link list to get the current Node or last Node which I dont want since during insertion of new Records already we have to traverse to reach to last Node thus storing the address of last Node.
But by doing the below I am not getting the proper values. Kindly someone suggest where I went wrong.
I am doing like this :
#include<stdio.h>
#include <stdlib.h>
struct Node
{
int data1;
int data2;
struct Node* next;
};
struct Node* head=NULL;
struct Node* ptr =NULL; /* Global pointer */
void insertNode(struct Node ** , struct Node* );
void fun1();
void fun2();
void fun1()
{
struct Node* ptr1 =NULL;
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
ptr1->data1=1; /* intilaizing with some values */
insertNode(&head,ptr1);
}
void fun2()
{
/* Updating the current Node in the linklist with new value . */
ptr->data2=2;
}
void insertNode(struct Node ** head, struct Node* NewRec)
{
if(*head ==NULL )
{
NewRec->next = *head;
*head = NewRec;
ptr=*head;
}
else
{
/* Locate the node before the point of insertion */
struct Node* current=NULL;
current = *head;
while (current->next!=NULL )
{
current = current->next;
}
NewRec->next = current->next;
current->next = NewRec;
ptr=current->next;
}
}
int main ()
{
fun1();
fun2();
while(head!=NULL)
{
printf("%d", head->data1);
printf("%d",head->data2);
head=head->next;
}
return 0;
}
You made a classic mistake.
This is wrong:
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
The allocated space here is sizeof(struct Node*) which is the size of a pointer (usually 4 or 8 bytes depending on the platform). But you need to allocate space for the whole struct Node structure, whose size is sizeof(struct Node).
So you simply need this:
ptr1 = (struct Node*)malloc(sizeof(struct Node));
BTW: in C you don't cast the return value of malloc so you actually should write this:
ptr1 = malloc(sizeof(struct Node));