I am practicing linked list structure while learning pointers and I have problem with appending item in list. Here is my code
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node {
int data;
node_t* next;
};
void append(node_t *head, int data) {
if (head == NULL) {
node_t *node = (node_t*)malloc(sizeof(node_t*));
node->data = data;
node->next = NULL;
head = node;
} else {
node_t *node = (node_t*)malloc(sizeof(node_t*));
node->data = data;
node->next = NULL;
if (head->next == NULL) {
head->next = node;
} else {
node_t *current = head;
while (1) {
if (current->next == NULL) {
current->next = node;
break;
}
current = current->next;
}
}
}
}
int main(void) {
node_t *head = NULL;
append(head, 4);
append(head, 6);
printList(head);
return 0;
}
My code breaks when I do head = node; It doesn't change value of head in main. I think I'm missing something but not sure what.
Thank you in advance
You are passing the pointer head by value in the function append. So the function deals with a copy of the passed to it pointer. Changing the copy does not influence on the original pointer. Either pass it by reference or return updated head from the function.
The first approach is much better.
The function can look the following way
int append( node_t **head, int data )
{
node_t *node = malloc( sizeof( node_t ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node
{
int data;
node_t *next;
};
int append( node_t **head, int data )
{
node_t *node = malloc( sizeof( node_t ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
void printList( node_t *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main(void)
{
node_t *head = NULL;
const int N = 10;
for ( int i = 0; i < N; i++ )
{
append( &head, i );
}
printList( head );
return 0;
}
Its output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
It seems the problem is you are passing the head pointer by value, so when you change it inside append(), you're only changing a local variable in that function - as opposed to the head variable within main().
This may be a bit confusing - if you pass a pointer, how can you be passing by value? Well, you might want to have a look at this question:
Is passing pointer argument, pass by value in C++?
... and the bottom line is that append() needs to take a node_t** head, and you'll call it from main with append(&head, 4);. See it working on Coliru.
Also you're allocating sizeof(node_t*) per node. You should be allocating sizeof(node_t).
It doesn't change value of head in main
Nor should it! If the value of head in main changed when you call append(), then your call to printList() would only print the last node in the list, and you'd have no way to refer to the other nodes in the list.
The reason that head isn't changed has been well explained in other answers, i.e. you're passing the head pointer by value. It's important to understand that the head in main() and the head parameter in append() are entirely different variables.
You pass the head of the list by value, so the append function cannot update the pointer in the caller's space, that happens to have the same name head. The head argument in append is a separate variable from the head local variable in main.
You should either pass a pointer to the head node so append can modify it:
void append(node_t **headp, int data) { ...
Or return the possibly modified head node to the caller which will store it back to its own variable:
node_t *append(node_t *head, int data) { ...
In both cases, it is advisable to signal memory allocation failure to the caller. Returning an error code in the first approach is easy, while returning a null pointer in the second approach can work, as long as the caller does not store the return value directly into its head variable, as in case of failure the previous value would be lost.
Here is a modified version with the first approach:
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node {
int data;
node_t *next;
};
// append a new node to the list, return 0 for success, -1 for allocation failure
int append(node_t **headp, int data) {
node_t *node = (node_t *)malloc(sizeof(node_t *));
if (node == NULL)
return -1;
node->data = data;
node->next = NULL;
if (*headp == NULL) {
*headp = node;
} else {
node_t *current = *headp;
while (current->next != NULL) {
current = current->next;
}
current->next = node;
}
return 0;
}
int main(void) {
node_t *head = NULL;
if (append(&head, 4) || append(&head, 6))
printf("node allocation error\n");
printList(head);
// should free the list
return 0;
}
Related
having segmentation error while trying to access nodes
i can create new nodes with my add function after function executes i cant access my nodes. i think they deallocated in memory but i couldnt figure it out.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *nextNode;
};
struct node *head;
void add(int data)
{
struct node *new = (struct node *)malloc(sizeof(struct node));
new->data = data;
new->nextNode = NULL;
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
printf("\nValue of temp1:%d\nValue of new: %d\n",temp1,new);
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
void printList()
{
int i = 1;
struct node *tempP;
tempP = head;
while (tempP != NULL)
{
printf("\nData of %dth element is : %d\n", i, tempP->data);
tempP = tempP->nextNode;
i++;
}
}
void main()
{
head = (struct node *)malloc(sizeof(struct node));
head->data = 10;
head->nextNode = NULL;
add(20);
add(30);
add(40);
printList();
}
This code snippet within the function add
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
is wrong. Within it there is changed the local variable temp1. It is not linked with the list.
Also using the conversion specifier %d to output a pointer invokes undefined behavior. You should use conversion specifier %p.
Using your approach to the function definition you could write instead.
void add(int data)
{
struct node *new = malloc( sizeof( *new ) );
new->data = data;
new->nextNode = NULL;
if ( head == NULL )
{
head = new;
}
else
{
struct node *temp1 = head;
while ( temp1->nextNode != NULL)
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new;
}
printf("\nValue of temp1->nextNode:%p\nValue of new: %p\n",
( void * )temp1->nextNode, ( void * )new);
printf("\nData of temp1->nectNode:%d\nData of new:%d\n",
temp1->nextNode->data,new->data);
}
Pay attention to that it is a bad design when functions depend on a global variable as in your case where the functions depend on the global variable head.
And it is also a bad idea when the first node is added to the list bypassing the function add.
And you need check whether a node was successfully allocated.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )
As for me I would declare the pointer to the head node in main like
int main( void )
{
struct node *head = NULL;
// ...
And the function add will look like
int add( struct node **head, int data )
{
struct node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->nextNode = NULL;
while ( *head != NULL ) head = &( *head )->nextNode;
*head = new_node;
}
return success;
}
and called like
struct node *head = NULL;
add( &head, 10 );
add( &head, 20 );
add( &head, 30 );
add( &head, 40 );
In turn the function printList can look like
void printList( const struct node *head )
{
for ( size_t i = 1; head != NULL; head = head->nextNode )
{
printf( "Data of %zuth element is : %d\n", i++, head->data);
}
}
And you need at least to write one more function that will free all the allocated memory.
There were a handful of mistakes in your add() function, which I've highlighted and fixed below:
void add(int data)
{
struct node *new = malloc(sizeof(*new)); // suggested by ryyker
new->data = data;
new->nextNode = NULL;
struct node *temp1 = head; // just keep it short
while (temp1->nextNode != NULL) // temp1 != NULL will always result in it being NULL, last node is the node with NULL as next
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new; // you want the next in the list to be the new node, not reassign the head to a new node. That's a memory leak.
// remember: temp1 == head, and head = new makes head lose the original node and point to the newly created one
printf("\nValue of temp1:%p\nValue of new: %p\n",temp1,new); // %p for pointers
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
Output:
Value of temp1:0x55809a4b22a0
Value of new: 0x55809a4b22c0
Data of temp1:10
Data of new:20
Value of temp1:0x55809a4b22c0
Value of new: 0x55809a4b26f0
Data of temp1:20
Data of new:30
Value of temp1:0x55809a4b26f0
Value of new: 0x55809a4b2710
Data of temp1:30
Data of new:40
Data of 1th element is : 10
Data of 2th element is : 20
Data of 3th element is : 30
Data of 4th element is : 40
I'm trying to learn data structures in C and I'm stuck at the first function I made.
If I run this nothing happens.
I get no errors but the program doesn't print anything.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
void insert(int data, node *head){
node *new_node = malloc(sizeof(node));
new_node->data = data;
head = new_node;
}
int main(){
node *head = NULL;
insert(8, head);
printf("head.data: %d\n", head->data);
}
But if I put the code from the function insert in the main function it works.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
int main(){
node *head = NULL;
node *new_node = malloc(sizeof(node));
new_node->data = 5;
head = new_node;
printf("head.data: %d\n", head->data);
}
Do I not know how to use functions in C or what is the problem with my first code?
In this call
insert(8, head);
the pointer head is passed to the function by value.
It means that the function deals with a copy of the value of the pointer.
Changing the copy within the function does not reflect on the original value of the pointer.
Either you need to pass the pointer by reference through a pointer to it or to return the new value of the pointer from the function and to assign it to the original pointer.
Also you forgot to set the data member next of the created node to NULL or more precisely to head.
Here you are.
int insert( node **head, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
and the function is called like
insert( &head, 8 );
or
if ( !insert( &head, 8 ) )
{
puts( "Error: not enough memory." );
}
Another approach is to return the new value of the pointer head from the function.
For example
node * insert( node *head, int data )
{
node *new_node = malloc( sizeof( node ) );
if ( new_node != NULL )
{
new_node->data = data;
new_node->next = head;
}
return new_node;
}
In this case you need to use the function with caution.
For example
node *tmp = insert( head, 8 );
if ( tmp != NULL )
{
head = tmp;
}
else
{
puts( "Error: not enough memory." );
}
The variable head in main and the variable head in insert are two different variables. When in insert you assign something to that local variable, it does not affect the variable head in main.
You can solve this in different ways. One is to pass the address of head to the function, so insert can actually modify what is at that address:
Not your question, but you should also initialise the next member of new_node:
void insert(int data, node **headPtr){
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = *headPtr;
*headPtr = new_node;
}
int main(){
node *head = NULL;
insert(8, &head);
printf("head.data: %d\n", head->data);
}
i'm working on a program in c language in which I have to use linked-list and in this program I have to insert the new node at the start of the linked-list if the user pass the value of the place 0 and also insert the new node at the end of the linked-list if the user pass the value of the place 1 in the choice variable. But i'm not getting any output on console and my program ends by just writing Output:
I can't figure out the problem in my code and here's my code.
/*
program for making nodes and adding them in memory as per 0
and 1
0 means that insert the number at front , in other words insert number after head
1 means insert number at the last place
First you need to input a number and then enter the place you want to insert it by giving input as 0 and 1
*Recall what does 0 and 1 mean by looking at line 5-7 respectively.
Just like
5 0 6 1 7 0 8 1
*/
#include <stdio.h>
#include <stdlib.h>
// declaring struct with typedef for ease of use
typedef struct node
{
int data;
struct node *next;
}node;
// declarations of functions use for this program respectively
void free_node(struct node *head);
void insert_at_beg(int num, struct node *head);
void insert_at_end(int num, struct node *head);
void print_node(struct node *head);
int main(void)
{
struct node *head = NULL;
int n;
// taking input
printf("Input number of nodes: ");
scanf("%d",&n);
int num, choice;
printf("\nInput data for nodes->\n");
// loop which takes value and choice
for (int i = 0; i < n; i++)
{
num = 0, choice = 0;
printf("\nInput data for the %d node: ", i+1);
scanf("%d",&num);
do
{
printf("Input place for the %d node: ", i+1);
scanf("%d",&choice);
}
while (choice != 1 && choice != 0);
if (choice == 0)
{
// function to insert node at front of head
insert_at_beg(choice, head);
}
else
{
// function to insert node at last place
insert_at_end(choice, head);
}
}
// function to print nodes
print_node(head);
// function to free memory made by malloc()
free_node(head);
}
// function to free the nodes
void free_node(struct node *head)
{
struct node *temp = head;
while(temp != NULL)
{
free(temp);
temp = temp->next;
}
}
// function for inserting number at front
void insert_at_beg(int num, struct node *head)
{
struct node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
printf("Can't allocate memory.");
exit (1);
}
new_node->data = num;
new_node->next = head;
head = new_node;
}
// function for inserting node at end
void insert_at_end(int num, struct node *head)
{
struct node *new_node, *last_node = NULL;
new_node = malloc(sizeof(node));
if (new_node == NULL)
{
printf("Can't allocate memory.");
exit (1);
}
if (head == NULL)
{
new_node->data = num;
new_node->next = NULL;
head = new_node;
}
last_node = head;
new_node->data = num;
new_node->next = NULL;
while (last_node->next != NULL)
{
last_node = last_node->next;
}
last_node->next = new_node;
}
//function for printing nodes
void print_node(struct node *head)
{
printf("\nOutput: \n");
struct node *temp = head;
while(temp != NULL)
{
printf("%d ",temp->data);
temp = temp->next;
}
}
You need to pass the pointer to the head node by reference to your functions insert_at_beg and insert_at_end and desirable to the function free_node.
Passing by reference in C means passing an object indirectly through pointer to it.
So for example the function insert_at_beg can look the following way. Pay attention to that such a function should not issue any message. It is the caller of the function that decides whether to output a message or not.
// function for inserting number at front
int insert_at_beg( struct node **head, int num )
{
struct node *new_node = malloc( sizeof( struct node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = num;
new_node->next = *head;
*head = new_node;
}
return success;
}
Correspondingly the function insert_at_end can look the following way
// function for inserting node at end
int insert_at_end( struct node **head, int num )
{
struct node *new_node = malloc( sizeof( struct node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = num;
new_node->next = NULL;
while ( *head != NULL )
{
head = &( *head )->next;
}
*head = new_node;
}
return success;
}
The function free_node has undefined behavior because you are using the pointer temp to access the memory that was already freed.
free(temp);
temp = temp->next;
The function can be defined the following way
// function to free the nodes
void free_node( struct node **head )
{
while( *head != NULL )
{
struct node *temp = *head;
head = &( *head )->next;
free( temp );
}
}
The functions can be called like
insert_at_end( &head, num );
or
if ( !insert_at_end( &head, num ) )
{
printf( "There is no enough memory to insert the value %d\n", num );
}
The parameter of the function print_node should have the qualifier const because the list is not changed within the function
//function for printing nodes
void print_node( const struct node *head )
{
printf("\nOutput: \n");
const struct node *temp = head;
//...
C is a pass-by-value language -- values passed to functions are copied and changes to the parameter in the function do not affect the caller. So head never becomes non-null in main; the assignment to head in insert_at_end is local and does not update the head pointer in main.
I have found other questions that were similar but not quite exactly the same, if I'm mistaken please leave a link :)
I've been trying to implement a shell with C and while parsing with pipes in mind I thought about using a linked list of char** args .
My parsing function has issues returning the entire list. I use a tmp node to keep moving while creating new nodes, but when I want to return the original head, it's next is NULL, I thought the pointer tmp to my head was supposed to be just a pointer and that changes have to be made on my head.
Here is simplified code with only the issue.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* next;
} node ;
node* foo()
{
node* head=malloc(sizeof(node));
node* tmp=head;
int i=0;
for(i=0;i<5;i++)
{
tmp=tmp->next;
tmp=malloc(sizeof(node));
tmp->data=i;
}
return head;
}
int main()
{
node* list=foo();
while(list)
{
printf("this is your %d\n",list->data);
list=list->next;
}
}
if you could just point me in the right direction or tell me what I'm getting wrong that'll be great.
node* head=malloc(sizeof(node));
node* tmp=head;
int i=0;
for(i=0;i<5;i++)
{
tmp=tmp->next;
tmp=malloc(sizeof(node));
tmp->data=i;
}
return head;
Here you have created head and gave space, but you have never initialized it and returning it before you initialized it
The function does not make sense because the data member next of each allocated node is not initialized. It is the variable tmp that is being changed in the loop.
The function can look the following way
node* foo()
{
const int N = 5;
node *head = NULL;
node **current = &head;
for ( int i = 0; i < N; i++ )
{
*current = malloc(sizeof( node ) );
if ( *current )
{
( *current )->data = i;
( *current )->next = NULL;
current = &( *current )->next;
}
}
return head;
}
Instead of using the magic number 5 it is better to specify how many nodes should be created in the list and the initial value as function parameters.
For example
node* foo( size_t n, int init_value )
{
node *head = NULL;
node **current = &head;
for ( size_t i = 0; i < n; i++ )
{
*current = malloc(sizeof( node ) );
if ( *current )
{
( *current )->data = init_value++;
( *current )->next = NULL;
current = &( *current )->next;
}
}
return head;
}
Take into account that in main the pointer list is overwritten in the loop. So you will not be able to access the list one more because the address of the head node will be lost. Use an intermediate variable. For example
int main( void )
{
node *list = foo();
for ( node *current = list; current != NULL; current = current->next )
{
printf("this is your %d\n", current->data);
}
}
And according to the C Standard the function main without parameters shall be declared like
int main( void )
You need to malloc tmp->next before assigning it to tmp, like this:
for(i=0;i<5;i++)
{
tmp->next = malloc(sizeof(node));
tmp=tmp->next;
tmp->data=i;
tmp->next = NULL;
}
This outputs:
this is your 0
this is your 0
this is your 1
this is your 2
this is your 3
this is your 4
I want to insert a node at the beginning of linked list, whenever insertAtBeginning method is called. My code builds well, but i don't get the desired output.
I get the following output:
0------>NULL
The desired output is:
9------>8------>7------>6------>5------>4------>3------>2------>1------>0------>NULL
Following is my code:
#include<stdio.h>
#include<stdlib.h>
struct dll{
int data;
struct dll* previous;
struct dll* next;
};
struct dll* insertAtBeginning(int a, struct dll* head){
if(head == NULL){
head->data = a;
head->previous = NULL;
head->next = NULL;
return head;
}
else{
struct dll *first;
first = (struct dll*) malloc( sizeof(struct dll));
first->data = a;
first->next = head;
head->previous = first;
first->previous = NULL;
head = first;
free(first);
return head;
}
}
void display_from_first(struct dll* head){
struct dll *temp;
temp = head;
printf("\nThe linked list contains: ");
while(temp != NULL) {
printf("%d------>",temp->data);
temp = temp->next;
}
printf("NULL\n");
free(temp);
}
int main(){
int i = 0;
struct dll *head1, *tail1;
head1 = (struct dll*) malloc( sizeof(struct dll));
head1->next = NULL;
head1->previous = NULL;
for(i=0; i<10; i++){
insertAtBeginning(i, head1);
}
display_from_first(head1);
return 0;
}
The code for a doubly linked list is much cleaner if you start with an empty list of two nodes as shown below.
That way you don't have to deal with special cases like if(head==NULL). There's always a node before and after the node that is being inserted (or deleted), so you just hook things up and you're done.
#include <stdio.h>
#include <stdlib.h>
typedef struct s_node Node;
struct s_node
{
Node *prev;
Node *next;
int data;
};
Node *insertAtBeginning( Node *head, int value )
{
// allocate memory for the new node
Node *node = malloc( sizeof(Node) );
if ( node == NULL )
return NULL;
// insert the node at the beginning of the list
Node *temp = head->next;
head->next = node;
temp->prev = node;
// fill in the fields of the node
node->prev = head;
node->next = temp;
node->data = value;
return node;
}
void showList( Node *head )
{
Node *node;
printf( "The list contains: " );
for ( node = head->next; node->next != NULL; node = node->next )
printf( "%d--->", node->data );
printf( "NULL\n" );
}
int main( void )
{
// create an empty list with two nodes
Node head = { NULL , NULL, 0 };
Node tail = { &head, NULL, 0 };
head.next = &tail;
// insert more nodes
for ( int i = 0; i < 10; i++ )
insertAtBeginning( &head, i );
// display the list
showList( &head );
}
There are mainly two problems here :
free(first) : This is not required as you wish to save the memory you just allocated, not delete it.
Your insertAtBeginning() function returns a pointer to head, so in main(), where you are calling this function change it to head1=insertAtBeginning(i, head1); This way your head is also saved.
Here's the code with the two edits :
http://ideone.com/nXwc8z
You have several mistakes here.
1) Your function insertAtBeginning returns pointer to changed list, but you do not update pointer to head of list in the main function.
2) You are freeing just allocated pointer to new node in the insertion function. You think that you are freeing pointer, but actually you say that this place in memory is not needed more and so your node can't be there.
You can't free(first); in insertAtBeginning().
code here.
And btw when you have empty list your display_from_first() prints The linked list contains: 0------>NULL because of
head1 = (struct dll*) malloc( sizeof(struct dll));
head1->next = NULL;
head1->previous = NULL;
in main(). Remove it from main to have correct output