linked list program - c

I am expecting the below linked list program to print 1
but its not.can anyone figure out why?
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE *,int );
int main()
{
NODE *head=NULL;
add(head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE *q,int num)
{
NODE *temp;
temp = q;
if(q==NULL)
{
q=(NODE *)malloc(sizeof(struct node));
temp = q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}

Your local variable head in main() is not modified by your add() function. This means you are calling display() with a parameter of NULL.
You'll need to pass a NODE **q into add, then update it in add().

Your add method when called first time (when head == NULL) should add the first node to the list thus changing head to point to the newly allocated node.
But this does not happen as add does not communicate back the changed head to the caller.
To fix this you can either return the modified head from the function:
// call as before but assign the return value to head.
head = add(head,1);
.....
// return type changed from void to NODE *
NODE* add(NODE *q,int num)
{
// make the changes as before
// return the head pointer.
return q;
}
or you can pass the pointer head by address to the function add as:
// pass the address of head.
add(&head,1);
.....
// change type of q from NODE * to NODE **
void add(NODE **q,int num)
{
// same as before but change q to *q.
// any changes made to the list here via q will be visible in caller.
}

The add() function is modifying the q argument, but it is passing it by value. Then head remains NULL after the add() call.

The problem is in signature of add method, to make your program work you should pass pointer to pointer of NODE, like this
void add(NODE **,int );
and work with him.
Then in case
if(*q==NULL)
you can allocate memory and replace NULL pointer to new HEAD
by it
*q=(NODE*)malloc(sizeof(struct node));
So it will work.
The problem is when you allocate memory you just replace local copy of null pointer to NODE but it doesn't affect head in main function.

int main()
{
NODE *head=NULL;
add(head,1);
display(head);
NODE *head is local to main. It's value is NULL. You pass the value NULL to add, which then creates a NODE and sets its data to 1. You then return to main... ...where head is STILL NULL. You need to pass the address of head, so that it's actual value is changed in add(). You also need to change add() to work with a pointer.
Main should return EXIT_SUCCESS or EXIT_FAILURE. Don't typedef struct node; it's harmful to readability and you get no abstraction here from using it.

When you call Add the new head pointer never gets returned. So it still points to NULL.

Ah... you're getting tripped up by the pointers...
Essentially, if you want to modify "head", you need to send a reference to THAT... otherwise you are just modifying the pointer... Change your code to this:
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE **,int );
int main()
{
NODE *head=NULL;
add(&head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is ");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE **q,int num)
{
NODE *temp;
temp = *q;
if(*q==NULL)
{
*q=(NODE *)malloc(sizeof(struct node));
temp = *q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}

Related

how to delete head in a linked list in c?

This program should delete the N-node in a singly linked list. If i put N = 1 or N = 2 it's ok, the program works. But with N = 0 the output prints infinite nodes with random values (after deleting the node 0). I think the program can't see the new head. Thx for the help!
#include <stdio.h>
#include <stdlib.h>
#define N 0
struct node {
int data;
struct node *next;
};
void printlist(struct node *head){
struct node *current=head;
int i=0;
while (current!=NULL){
printf("node number %d \t : %d\n", i, current->data);
current=current->next;
i++;
}
}
int deletenode(struct node *head,int n){
struct node *current=head;
struct node *previous=head;
int i=0;
while(current!= NULL){
if (n==i && i!=0){
previous->next=current->next;
free(current);
return 1;
}
else if (n==i && i==0){
head=head->next;
free(current);
return 1;
}
i++;
previous=current;
current=current->next;
return 0;
}
printf("error\n");
exit(EXIT_FAILURE);
}
void main(){
struct node *n1=malloc(sizeof(struct node));
struct node *n2=malloc(sizeof(struct node));
struct node *n3=malloc(sizeof(struct node));
struct node *head=n1;
n1->data=5;
n1->next=n2;
n2->data=10;
n2->next=n3;
n3->data=15;
n3->next=NULL;
printf("\n\nbefore\n");
printlist(head);
deletenode(head,N);
printf("\n\nafter\n");
printlist(head);
}
I'm using currentas a temp pointer , because after the head shift on the second node i need a pointer to the old head and use free.
C always passes by value, so changing a parameter has no effect on the caller.
void foo(int i) {
i = 1234; // No effect on caller.
}
void foo(int *p) {
p = NULL; // No effect on caller.
}
If you want to modify a variable (such as the caller's head), you need to pass a pointer to it. (You can still change that to which a pointer references.)
int deletenode(struct node **head, int n) {
...
}
deletenode(&head, N);
Now, you could simply replace every instance of head in your code with (*head) to account for the new calling convention, but that would waste an opportunity for simplification. By having a pointer to a struct node *, we don't need to handle head (a struct node *) and prev_node->next (a struct node *) differently.
int delete_node_n(struct node **ptr, unsigned n) {
// Make `ptr` point to the pointer we want to modify.
// This will either be the `head` variable
// or the `next` field of some node.
while (1) {
if (!*ptr)
return 0;
if (!n)
break;
ptr = &( (*ptr)->next );
--n;
}
struct node *to_free = *ptr;
*ptr = (*ptr)->next;
free(to_free);
return 1;
}

How to change null pointer (of struct return type) to declared struct?

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;
}

Node pointer to current Node during mutile function call

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));

Passing typedef structure as call by reference in C

I am trying to create a linked list in C and my code is as below.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
}node_t;
void insert_into_list(node_t *,int);
void print_list(node_t *);
node_t *create_node(int );
void insert_into_list(node_t *head, int value){
node_t *temp ;
temp = create_node(value);
if(head == NULL){
printf("Inserting node for the first time\n");
head = temp;
}else {
head->next = temp;
}
}
void print_list(node_t *head){
node_t *current = head;
while(current!=NULL){
printf("%d----->",current->data);
current = current->next;
}
printf("NULL");
}
node_t *create_node(int value){
node_t *new_node = malloc(sizeof(node_t));
if(new_node==NULL){
printf("Memory allocation failed for the list creation. :(");
return NULL;
}
new_node->data = value;
new_node->next = NULL;
return new_node;
}
int main(int argc, char *argv[]) {
node_t *head = NULL;
insert_into_list(head,10);
if(head==NULL){
printf("Still head is NULL :(");
}else{
printf("Head is not NULL:)");
}
print_list(head);
return 0;
}
In main, I am calling insert_into_list and even after successful memory allocation, i am not able to get the head value with the newly created node. Still showing the value as NULL.
I have debugged with gdb and found that upto below code, head is not NULL
printf("Inserting node for the first time\n");
head = temp;
I thought I am passing by reference and expected the value to get reflected in the caller function.
Please correct me.
If you want to pass by reference (or rather, the equivalent) in C you must pass a pointer. To pass a pointer by reference you have to pass a pointer to the pointer.
So in e.g. insert_into_list you must declare head as a pointer to a pointer:
void insert_into_list(node_t **head, int value)
And use the dereference operator when accessing the head variable.
You call it using the address-of operator &:
node_t *head = NULL;
insert_into_list(&head,10);

Linked Lists in C, Random output?

#include <stdio.h>
struct list
{
int data;
struct list *next;
};
struct list *start, *end;
void add(struct list *head, struct list *list, int data);
void delete(struct list *head, struct list *tail);
int main(void)
{
start=end=NULL;
add(start, end, NULL);
add(start, end, NULL);
printf("First element: %d");
delete(start, end);
return 0;
}
void add(struct list *head, struct list *tail, int data)
{
if(tail==NULL)
{
head=tail=malloc(sizeof(struct list));
head->data=data; head->next=NULL;
} else {
tail->next=malloc(sizeof(struct list));
tail=tail->next;
tail->data=data;
tail->next=NULL;
}
}
void delete(struct list *head, struct list *tail)
{
struct list *temp;
if(head==tail)
{
free(head);
head=tail=NULL;
} else {
temp=head->next;
free(head);
head=temp;
}
}
I am aiming to return an output of 3 but keep getting random results. Any insight is greatly appreciated
As you want to modify head and tail you need to pass a pointer to them.
i.e.
void add(struct list **head, struct list **tail, int data)
{
if(*tail==NULL)
{
*head = *tail = malloc(sizeof(struct list));
(*head)->data = data;
(*head)->next = NULL;
} else {
(*tail)->next = malloc(sizeof(struct list));
*tail = (*tail)->next;
(*tail)->data = data;
(*tail)->next = NULL;
}
}
Do similarly for the other function. Then head and tail will also change outside the function.
The line
printf("First element: %d");
It requires an integer to print - supply it - see the manual page for printf
Avoid using keywords for C++ in C programs - such as delete
Parameters of C functions are passed by value. Thus, the changes that you make to the values of head and tail in the add() function will not be reflected in main() from which add() is called.
And, it doesn't seem that you've supplied a second parameter for printf(), so the %d format is not going to get the integer value that it will be looking for.
In your program start and end are global variables, so there is no need to pass it as arguments to other functions, because other methods can directly access it.
//Structure to store data
struct list
{
int data;
struct list *next;
};
// global variables
struct list *start, *end;
void add(int);
void delete();
// start of program
int main(void)
{
start=end=NULL;
add(5);
add(6);
printf("\nFirst element: %d",start->data);
delete();
printf("\nFirst element: %d",start->data);
return 0;
}
//add node to list
void add(int data)
{
if(end==NULL)
{
start=end=malloc(sizeof(struct list));
start->data=data; start->next=NULL;
} else {
end->next=malloc(sizeof(struct list));
end=end->next;
end->data=data;
end->next=NULL;
}
}
// delete node from list
void delete()
{
struct list *temp;
if(start==end)
{
free(start);
start=end=NULL;
} else {
temp=start->next;
free(start);
start=temp;
}
}
OUTPUT:
First element: 5
First element: 6
Note:
If you don't want your start and end to be global than it can be a local variable of main function. Here you have to either work on double pointer mechanism or return memory address to retain the modification.
There are a number of problems here.
First, when you pass a pointer to a function, the pointer is passed by value. Any changes to the pointer in the called function will not be reflected in the calling function. To change what the pointer in the calling function is pointing to, you need to pass a pointer-to-pointer. So your add()function needs to be:
void add(struct list **head, struct list **tail, int data) {
if(*tail == NULL) {
*head = *tail = malloc(sizeof(struct list));
(*head)->data = data;
(*head)->next = NULL;
}
else {
(*tail)->next = malloc(sizeof(struct list));
(*tail) = (*tail)->next;
(*tail)->data = data;
(*tail)->next = NULL;
}
return;
}
And your delete() function needs to be changed similarly.
Secondly, you are passing NULL as your data value to the add function. NULL is a pointer; it is typically defined as a macro, and could be (void*) 0 in the implementation. It should not be used as an integer. Pass 0 as the integer, not NULL.
Third, you have this statement:
printf("First element: %d");
Your format string has the conversion specifier %d but there is no argument that matches the %d. This is undefined behavior. What integer exactly are you trying to print?
Where do you expect the output 3, and for what reason?

Resources