delete the first node and take the head node data - c

I have this c program that delete the first node and show the node head data.
int Delete(struct node** head){
struct node *temp = headRef;
headRef = headRef->next;
tmp->next=NULL;
free(temp);
int headNode = headRef->data;
return headNode; }
I was not able to delete the first node but it give me error of request member 'data' and 'struct'

I don't understand where if headRef comes from.
Secondly, you only need to pass the head node into the function, therefore you need
struct node* head, not struct node** head
This is my code, I hope it helps you.
int Delete(struct node* head) {
struct node* temp = head;
struct node* nextNode = head -> next;
int headData = head -> data;
temp -> next = NULL;
free(temp);
head = nextNode;
return headData;
}

Related

why my append function in linked list not working?

the programme have runtime error when it want to add nodes to linked list (in executing append function).
i tested 'create' and 'prepend' function they do their parts correctly.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data ;
struct Node* next ;
};
struct Node* Head=NULL ;
struct Node* create(int ,struct Node*);
struct Node* prepend(int ,struct Node*);
struct Node* traverse(struct Node*);
struct Node* append(int ,struct Node*);
int main()
{
int data =4 , i ;
Head = prepend(data,Head);
for(i=0;i<3;i++){
scanf("%d",&data);
append(data,Head);
}
return 0;
}
create func for adding new nodes
struct Node* create(int data ,struct Node* Head){
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
if(newNode == NULL){
printf("Error\n");
exit(0);
}
newNode -> data = data ;
newNode -> next = Head ;
return newNode ;
}
adding new node at the first of linked list:
struct Node* prepend(int data ,struct Node* Head){
struct Node* newNode = create(data,Head);
Head = newNode ;
return Head ;
}
for returning last created Node:
struct Node* traverse(struct Node* Head){
struct Node* cursor = Head ;
while(cursor->next != NULL || cursor->next != Head){
cursor = cursor->next ;
}
return cursor ;
}
for adding new node to end of the linked list:
struct Node* append(int data ,struct Node* Head){
struct Node* newNode = create(data,Head);
struct Node* cursor = traverse(Head);
cursor->next = newNode ;
return newNode ;
}
you're not allocating enough bytes with
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
sizeof(struct Node *) is the size of a pointer, and your structure holds a pointer + another field, so that's undefined behaviour.
a correct way (using sizeof on the dereferenced pointer to get the proper size & not casting the return value of malloc):
struct Node* newNode = malloc(sizeof(*newNode));
the second issue is in your traverse function. When you do cursor = cursor->next, cursor can be NULL and you're testng cursor->next at the next iteration. Just iterate on the list & memorize the last non-NULL node instead (and drop the test for Head being the next element, because it's just not possible:
struct Node* traverse(struct Node* Head){
struct Node* cursor = Head;
struct Node* retval = cursor;
while (cursor != NULL) {
retval = cursor;
cursor = cursor->next;
}
return retval;
}
Change this :
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
to this:
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
The Segmentation Fault error comes from the traverse function and in the while's condition. It seems that NULL value can not be used in comparison and I now wonder why! By the way change this function as follow then try again:
struct Node* traverse(struct Node* Head){
struct Node* cursor = Head ;
while(cursor->next){
if(cursor->next == Head)
break;
cursor = cursor->next ;
}
return cursor ;
}

Passing a linked list head through a function as address in C

I have a question regarding passing the head of a linked list in C through a function. So the code goes something like this:
#include <stdio.h>
//Defining a structure of the node
struct node {
int data;
struct node* next;
};
void insert (struct node* rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
rec = temp; // head and rec is now pointing to the same node
}
void print(struct node* rec){
printf("%d", rec->data); //error occurs here
puts("");
}
main(){
struct node *head = NULL; //head is currently pointing to NULL
insert (head, 5); //Passing the head pointer and integer 5 to insert()
print(head);
}
So as you see, the error occurs when I tried printing rec->data. Why did the error occur? I thought since the pointer rec and head are all pointing to the same node in the heap, there should not be any problem?
Thank you.
You could pass a struct node** as suggested by #sje397.
However, I would suggest the following design (which, in my opinion is easier to reason about too):
/* returns the new head of the list */
struct node *insert (struct node* current_head, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = current_head;
return temp;
}
and use it like
head = insert(head, 5);
In this case I would also rename the function something like push_front.
Just for completeness, I think #sje397 meant something like the following (Typical linked list code rewritten again and again by every C programmer...):
void insert(struct node **head, int x) {
struct node* new_head = (struct node*)malloc(sizeof(struct node));
new_head->data = x;
new_head->next = *head;
*head = new_head;
}
In C there is no pass by reference.
Your insert function isn't inserting a node in the list, its just changing the node which the head points to. Because of temp->next = NULL the list will always contain two nodes.
Another error is that you're just modifying a local copy of the head node.
To fix this You have 3 choices:
-You can make the head node global
-You can pass a pointer to the head node(pointer to pointer) to the function.
-You can return the modified head node by the function.
Redefine the insert function to:
void insert (struct node** rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
*rec = temp; // head and rec is now pointing to the same node
}

Accessing fields of a struct for a double linked list

I want to make a double linked list and I have a problem with accessing fields in the struct. This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int val;
struct node * next;
struct node * prev;
}node;
void insert(int val, node **head)
{
node * temp= *head;
node * temp2=(node *)malloc(sizeof(node));
node * temp3=(node *)malloc(sizeof(node));
temp2->val=val;
temp2->prev=NULL;
temp2->next=*head;
*head=temp2;
temp2->next->prev=temp2;
}
void print(node* head)
{
node* temp=head;
while(temp!=NULL)
{
printf("%d ", temp->val);
temp=temp->next;
}
}
int main()
{ node * head=NULL;
insert(1, &head);
insert(2, &head);
print(head);
return 0;
}
I get a crash at temp2->next->prev, and I don't understand why. Am I not allowed to access the prev field of the temp2->next node? I tried writing (temp2->next)->prev but also doesn't work. Is there any way that I cant make that work?
When you insert the first node, *head, and therefore temp->next, is NULL. Check that case:
void insert(int val, node **head)
{
node *temp= malloc(sizeof(*temp));
temp->val = val;
temp->prev = NULL;
temp->next = *head;
*head = temp;
if (temp->next) temp->next->prev = temp;
}
(I've removed the unused variables and lost the cast on malloc.)
A doubly linked list should probably have a tail, too. In that case, update the tail when you append an item at the head of an empty list.
try this:
void insert(int val, node **head)
{
if(*head == NULL){
node * temp2=(node *)malloc(sizeof(node));
temp2->val=val;
*head = temp2;
}
else{
node * temp= *head;
node * temp2=(node *)malloc(sizeof(node));
temp2->val=val;
temp2->prev=NULL;
temp2->next=temp;
temp->prev = temp2;
}
}
Most likely head was not initialized
As I have understood you always insert a new node before the head though in double linked list you have to add new nodes usually at the tail of the list. As a double linked list usually have two sides then there is a sense to define two functions: push_front and push_back. Your function insert corresponds to function push_front.
Nevertheless function insert could look the following way
void insert( int val, node **head )
{
node *temp = ( node * )malloc( sizeof( node ) );
temp->val = val;
temp->prev = NULL;
temp->next = *head;
if ( *head ) ( *head )->prev = temp;
*head = temp;
}
It would be better if you would define one more structure named as for example List (or whatever) and that could be defined as
struct List
{
node *head;
node *tail;
};
Also you could add one more data member - a count of the nodes in the list, For example
struct List
{
node *head;
node *tail;
size_t count;
};
Also do not forget to write a function that would delete all nodes of the list when it is not needed any more.

Incompatible pointer type error using structs

I am new to programming. I am trying to learn C and pointers, but it is giving me much trouble.
I got the following error trying to implement a singly linked list. I searched online, and I couldn't find someone who had an error just like mine, or perhaps I just didn't couldn't make sense of it with my problem.
The following is the error I received:
warning: incompatible pointer types initializing 'NODE *'
(aka 'struct node *') with an expression of type 'struct NODE '
[-Wincompatible-pointer-types]
NODE temp = (*l)->head;
NODE* temp = (*l)->head;
In main, I passed the address of the variable of type LIST. So, I thought I had to dereference 'l', to get the address of where the LIST type is located, then I had to dereference with an arrow to get the address of where the NODE is located. Where am I confused? I do appreciate the help.
Below you will see the code I have written:
typedef struct node {
int value;
struct node* next;
}NODE;
typedef struct list{
struct NODE* head;
}LIST;
void insert(LIST** l, int x){
if((*l)->head == NULL){
NODE* new_Node = (NODE*) malloc(sizeof(NODE));
new_Node->next = NULL;
new_Node->value = x;
}
NODE* temp = (*l)->head;
while(temp->next != NULL){
temp=temp->next;
}
NODE* new_Node = (NODE*) malloc (sizeof(NODE));
temp->next = new_Node;
new_Node->next = NULL;
new_Node->value = x;
}
int main(){
LIST *l = (LIST*) malloc(sizeof(LIST));
insert(&l, 5);
return 0;
}
I guess your problem is here :
typedef struct list
{
struct NODE* head;
}LIST;
just remove struct keyword before NODE
typedef struct list
{
NODE* head;
}LIST;
or
typedef struct list
{
struct node* head;
}LIST;
Also you need to initialize the head with NULL to make this condition to wwork
if((*l)->head == NULL) .....
so when you create your list add l->head = NULL;
LIST *l = malloc(sizeof(LIST));
l->head = NULL;
And the last one (i hope) when you create your first node, you forget to assign head to it, and return in order not to add the first element twice
if((*l)->head == NULL)
{
NODE* new_Node = malloc(sizeof(NODE));
new_Node->next = NULL;
new_Node->value = x;
(*l)->head = new_Node;
return;
}
And BTW, don't cast malloc results in C
This:
typedef struct list{
struct NODE* head;
}LIST;
Should be this:
typedef struct list{
NODE* head;
}LIST;
Tested and compiles fine with that change.
Your use of *l is correct. The problem is with the line:
NODE* temp = (*l)->head;
The left-hand side is NODE *, which is the same as struct node *, however the right-hand side is struct NODE *.
C is case-sensitive, struct node and struct NODE are different types. Also, the namespace of struct tags is separate to that of other types, so NODE and struct NODE are also different types.
I think you meant, in LIST's definition, that struct NODE* head; should be NODE* head;. There is no warning generated on that line, because in C it's legal to implicitly declare a struct type just by mentioning it (i.e. this line declares the new type struct NODE also).
There is code repetition in your insert function. You should not use the struct keyword before NODE in the second typedef statement because NODE is already an alias for the type struct node. That's why you are getting the warning mentioned in your question. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc?
I suggest the following changes to your code.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *next;
} NODE;
typedef struct list {
NODE *head;
} LIST;
void insert(LIST **l, int x) {
// do not cast the result of malloc.
// also, do not repeat the type on the rhs.
// create the new node to be inserted
NODE *new_Node = malloc(sizeof(*new_Node));
new_Node->next = NULL;
new_Node->value = x;
NODE *temp = (*l)->head;
// check if the head of the list is empty
// if yes, simply assign the new node to head
// and return
if(temp == NULL) {
(*l)->head = new_Node;
return;
}
// reach the last node in the list
while(temp->next != NULL)
temp = temp->next;
// insert the new node to the end of the list
temp->next = new_Node;
}
int main(void) {
LIST *l = malloc(sizeof(*l));
insert(&l, 5);
insert(&l, 10);
// print the value of the head node
printf("%d\n", l->head->value);
// print the value of the next node
printf("%d\n", l->head->next->value);
NODE *head = l->head;
NODE *temp = NULL;
// free the nodes in the list
while(head != NULL) {
temp = head;
head = head->next;
free(temp);
}
// free the pointer to the
// head of the list
free(l);
return 0;
}

deleteNode Function Errors

This is my delete node function, can anyone help me in seeing what is wrong with it? I seem to be having a lot of trouble as I do not understand some parts of it.
How is the pointer to the head suppose to be used? struct lnode** head, I know this is a pointer to the head pointer. However I am not sure if I am using it correctly.
The second part of the code, I am not sure if I am correctly connecting the two nodes after deleting the one that the function calls.
void deleteNode (struct lnode** head, struct lnode* node) {
if((*head) == node){
struct lnode* temp = (*head) -> next;
free(node);
free(node->word);
*head = temp;
}
else{
struct lnode *nextNode = node->next;
struct lnode *prevNode;
while((*head) != NULL){
if((*head)->next = node){
prevNode = *head;
break;
}
else
*head = (*head) -> next;
}
prevNode->next = nextNode;
free(node);
free(node->word);
}
}
Please try with this modified program. In the original program, there were the following issues.
If the node to be deleted matched with head, then you were freeing the node twice. This will give an exception as you are trying to free a memory which already has been freed.
The comparison in if condition required to be if((*head)->next == node) instead of if((*head)->next = node)
The order of freeing memory is important. Hence node->word should be freed prior to freeing of node.
void deleteNode (struct lnode** head, struct lnode* node) {
struct lnode *prevNode = *head;
if((*head) == node){
struct lnode* temp = (*head) -> next;
*head = temp;
}
else{
struct lnode *nextNode = node->next;
while((*head) != NULL){
if((*head)->next == node){
prevNode = *head;
break;
}
else
*head = (*head) -> next;
}
prevNode->next = nextNode;
free(node->word);
free(node);
}
}

Resources