say I have the following code for inserting a node at the end to a linkedlist:
int main() {
struct Node* head = NULL;
newNode(head, 1);
newNode(head, 2);
newNode(head, 3);
print(head);
return 0;
}
void newNode(struct Node* head, int val) {
struct Node* curr_p = head;
struct Node* new_p = malloc(sizeof(struct Node));
new_p->data = val;
new_p->next = NULL;
if (head == NULL) {
curr_p = new_p;
// printf("head %d \n", head->data);
}
else{
while (curr_p->next != NULL) {
curr_p = curr_p->next;
}
curr_p->next = new_p;
}
}
void print(struct Node* head) {
struct Node* curr_p = head;
while (curr_p != NULL) {
printf("%d\n", curr_p->data);
curr_p = curr_p->next;
}
}
It appears what causes the error is in the if statement block where head == NULL, the head node pointer seems to unable to point to new node. I always ended up with a segmentation fault. any reason for this?
I guess that your fault is that you are passing the head pointer in value not in reference so the code doesn't change it's value because it just copies the pointer
so your code should look like this
newNode(struct Node** head , int val ) {
struct Node* curr_p = *head;
/*
*/
if(curr_p == NULL ) {
*head = new_p;
}/*....*/
}
and in the main
newNode(&head,1)
and the finale code would be
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node * next;
};
void newNode(struct Node** head, int val) {
struct Node* curr_p = *head;
struct Node* new_p =malloc(sizeof(struct Node));
new_p->data = val;
new_p->next = NULL;
if ( curr_p == NULL) {
*head = new_p;
// printf("head %d \n", head->data);
}
else{
while (curr_p->next != NULL) {
curr_p = curr_p->next;
}
curr_p->next = new_p;
}
}
void print(struct Node* head) {
struct Node* curr_p = head;
while (curr_p != NULL) {
printf("%d\n", curr_p->data);
curr_p = curr_p->next;
}
}
int main() {
struct Node* head = NULL;
newNode(&head, 1);
newNode(&head, 2);
newNode(&head, 3);
print(head);
return 0;
}
and actually you don't have to use curr_p in the print function because the head pointer in the print function it's just a copy of the head pointer of the main function so it wouldn't change it's value if you do something like head = head->next ; in the print function .
You have not specified that where you are getting segmentation fault but my strong guess is that you would be getting at - printf("head %d \n", head->data);. Why? Because with your present code head is NULL (that's what you are passing from your main method) and then you try to de-reference a NULL then you WILL segmentation fault.
You must only de-reference a valid pointer. If the pointer variable is holding NULL or some uninitialized/default value then de-referencing it will result in segmentation fault.
Below is the fixed IF block.
if (head == NULL) {
head = new_p;
printf("head %d \n", head->data);
}
Related
I have looked at my code several times but couldn't find the problem. please tell me what I need to replace to get my code working.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert(int x)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head == NULL)
{
temp->next = head;
head = temp;
return;
}
struct node *temp1 = head;
while(temp1 != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
void display()
{
struct node *temp = head;
if (head == NULL)
{
printf("list is empty");
return;
}
else{
while(temp!=NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
}
int main()
{
head = NULL;
insert(3);
insert(5);
insert(6);
display();
}
The problem is in this code:
struct node *temp1=head;
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
... the while loop won't end until temp1 is NULL, so after the loop ends, it is guaranteed that temp1 is a NULL pointer ... and then you dereference that NULL pointer (via temp1->next), which causes a crash. Probably what you want to do instead is while(temp1->next != NULL) {...}
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
The only way out of this loop is for temp1 to be NULL. Then the next line attempts to used temp1 as a pointer. This is likely causing your issue. You need to instead check if the next is NULL and break leaving temp1 as the last in the list not it's next.
Pro tip for linked lists like this, they are a lot easier to modify with double pointers. Example code:
void append(struct node **list, int a) {
// skip to the end of the list:
while (*list != NULL) {
list = &(*list)->next;
}
*list = malloc(sizeof(struct node));
(*list)->data = a;
(*list)->next = NULL;
}
void display(struct node *list) {
while (list) {
printf("%d\n", list->data);
list = list->next;
}
}
void remove(struct node **list, int index) {
while (*list) {
if (--index == 0) {
struct node *temp = *list;
*list = temp->next;
free(temp);
break;
}
}
}
int main() {
struct list *mylist;
append(&mylist, 3);
append(&mylist, 4);
append(&mylist, 5);
display(mylist); // prints 3 4 5
remove(&mylist, 1);
display(mylist); // prints 3 5
remove(&mylist, 0);
remove(&mylist, 0);
// mylist is NULL again, all memory free'd
}
Note that this code needs no special cases for "is the list empty?", which makes it less complex than yours.
Please see the full code below.
I have an initial array named arr.
I'm using a linked list to store some indices via the append function. After I got the indices, I store them in linked list and use clearList to change the corresponding values to 0 (In this example arr[2] and arr[4]).
Finally, I free the memory by calling freeList since i'm done with the linked list.
However, to be able to do same thing again and again, I need to set head to NULL whenever I call freeList. But I cannot. Any idea how to solve this?
Thank you.
#include <stdio.h>
#include "gurobi_c.h"
#include <stdlib.h>
//Gurobi variables
GRBenv *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables
struct Node
{
int data;
struct Node *next;
struct Node *end;
};
void append(struct Node** head_ref, int new_data)
{
struct Node *last = *head_ref;
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
new_node->end = new_node;
if (*head_ref == NULL)
{
*head_ref = new_node;
//printf(" ..Init Append %d\n",new_data);
return;
}
last = (*head_ref)->end;
last->next = new_node;
(*head_ref)->end=new_node;
//printf(" ..Append %d\n",new_data);
return;
}
void clearList(struct Node *node, double *arr)
{
int i;
if(node!=NULL)
{
struct Node tmp;
tmp=*(node->end);
while (node != NULL)
{
i=node->data;
arr[i]=0;
//printf(" ..clear %d \n", node->data,(node->end)->data);
node = node->next;
}
}
}
void freeList(struct Node *node)
{
struct Node *tmp,*hd;
hd=node;
while (node != NULL)
{
tmp=node;
node = node->next;
//printf(" ..Free %d \n", tmp->data);
free(tmp);
}
hd=NULL;
}
int main (){
Node *head;
double *arr = (double *) malloc(sizeof(double) * 10);
for(int i=0;i<10;i++)
arr[i]=i;
head=NULL;
printf("Head: %s\n", head);
append(&head,2);
append(&head,4);
clearList(head,arr);
for(int i=0;i<10;i++)
printf("No %d : %.2f\n",i,arr[i]);
freeList(head);
free(arr);
printf("%s", head);
getchar();
return 0;
}
You're already changing the value of head in your append function so you basically need to do the same thing in freeList:
void freeList(struct Node **head_ref)
{
struct Node *tmp,*node;
node=*head_ref;
while (node != NULL)
{
tmp=node;
node = node->next;
//printf(" ..Free %d \n", tmp->data);
free(tmp);
}
*head_ref=NULL;
}
int main (){
/* do stuff */
freeList(&head);
/* do stuff */
}
Just for completeness: Another possible option would be to use a wrapper macro for freeList().
void freeList(struct Node *node)
{
/* ... */
}
#define freeListNull(node) do { \
freeList(node); \
node = NULL; \
} while(0)
int main () {
/* ... */
freeListNull(head);
/* ... */
}
This solution has a similar disadvantage as the version that returns the modified pointer. You can simply forget to use the right call freeListNull(head); and call freeList(head); instead. The best solution is a function freeList() that takes the address of the head pointer as in idk's answer.
I realized it is possible to change the freeList function so that it will return a NULL value. See the updated code below:
#include <stdio.h>
#include "gurobi_c.h"
#include <stdlib.h>
//Gurobi variables
GRBenv *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables
struct Node
{
int data;
struct Node *next;
struct Node *end;
};
void append(struct Node** head_ref, int new_data)
{
struct Node *last = *head_ref;
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
new_node->end = new_node;
if (*head_ref == NULL)
{
*head_ref = new_node;
//printf(" ..Init Append %d\n",new_data);
return;
}
last = (*head_ref)->end;
last->next = new_node;
(*head_ref)->end=new_node;
//printf(" ..Append %d\n",new_data);
return;
}
void clearList(struct Node *node, double *arr)
{
int i;
if(node!=NULL)
{
struct Node tmp;
tmp=*(node->end);
while (node != NULL)
{
i=node->data;
arr[i]=0;
//printf(" ..clear %d \n", node->data,(node->end)->data);
node = node->next;
}
}
}
Node* freeList(struct Node *node)
{
struct Node *tmp;
while (node != NULL)
{
tmp=node;
node = node->next;
printf(" ..Free %d \n", tmp->data);
free(tmp);
}
return NULL;
}
int main (){
Node *head;
double *arr = (double *) malloc(sizeof(double) * 10);
for(int i=0;i<10;i++)
arr[i]=i;
head=NULL;
printf("Head: %s -> null as expected\n", head);
append(&head,2);
append(&head,4);
clearList(head,arr);
for(int i=0;i<10;i++)
printf("No %d : %.2f\n",i,arr[i]);
printf("Head: %s -> Not null as linkedlist is not freed\n", head);
head=freeList(head);
printf("Head: %s -> Again null as expected\n", head);
free(arr);
printf("%s", head);
getchar();
return 0;
}
I am trying to implement a singly linked list in C and have trouble to create the Head node.
my code looks like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE{
int value;
struct NODE* next;
}node;
int append(node* head, int val){
if(head == NULL){
printf("Head is NULL");
head = malloc(sizeof(node));
if(head == NULL){
return EXIT_FAILURE;
}
head->value = val;
head->next = NULL;
} else {
printf("Head is not NULL");
while(head->next != NULL){
head = head->next;
}
head = malloc(sizeof(node));
head->value = val;
head->next = NULL;
}
return EXIT_SUCCESS;
}
int main(){
node* head = NULL;
append(head, 10);
append(head, 5);
append(head, 7);
return EXIT_SUCCESS;
}
when adding nodes, memory for the head should be allocated and then filled with the arguments, if it does not already exist. I can't figure out, why the Head always stays NULL.
Can anybody explain this to me?
I appreciate any help.
Thanks in advance :)
head is always NULL, because you are not modifying it, you are modifying its copied value instead.
In main(), do this:
append(&head, 10); // Modify head itself and not its copied value
Change the function signature to this:
int append(node** head, int val)
inside the function append() replace head with *head everywhere
There is one more problem with your code. In append() , there is no need of the while loop, since you will be permanently shifting the head to the end. You should not do this because head should always point to "head" of the linked list.
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE
{
int value;
struct NODE *next;
} node;
int
append (node **head, int val)
{
if (*head == NULL)
{
printf ("Head is NULL");
*head = malloc (sizeof (node));
if (*head == NULL)
{
return EXIT_FAILURE;
}
(*head)->value = val;
(*head)->next = NULL;
}
else
{
printf ("Head is not NULL");
node * temp = malloc (sizeof (node));
temp->value = val;
temp->next = *head;
*head = temp;
}
return EXIT_SUCCESS;
}
int
main ()
{
node *head = NULL;
append (&head, 10);
append (&head, 5);
append (&head, 7);
return EXIT_SUCCESS;
}
Output:
Head is NULLHead is not NULLHead is not NULL
I found this on Internet to reverse a list using recursion and applied it in codeblocks but the output only reverse prints last two Insert call from main function. It skips the first three Insert calls. Why? I did search for this problem here but I failed to understand them as I'm a beginner. Kindly help
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
struct Node* Insert (struct Node* head, int data)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
struct Node* head = NULL;
head = Insert(head,2);
head = Insert(head,7);
head = Insert(head,3);
head = Insert(head,1);
head = Insert(head,4);
reversePrint(head);
return 0;
}
O/P : 4 1
NOTES:
Don't cast the return of value of malloc
You declared two *head and confused yourself
No need to pass pointer to function and return pointer when you have head declared as global. Which is not a good idea but I followed your code.
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
void Insert (int data)
{
struct Node* temp = malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
Insert(2);
Insert(7);
Insert(3);
Insert(1);
Insert(4);
reversePrint(head);
return 0;
}
OUTPUT:
4 1 3 7 2
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
int insert (struct node *head, int data);
int print (struct node *head);
int main()
{
struct node *head;
head = NULL;
// printf("%d\n",head);
insert(&head,5);
insert(&head,4);
insert(&head,6);
print(&head);
print(&head);
print(&head);
}
int insert(struct node *head,int data) {
if(head == NULL) {
head = malloc(sizeof(struct node));
head->next = NULL;
head->data = data;
// printf("%d\n",data);
}
else {
struct node *tmp = head;
if(tmp->next!=NULL) {
tmp = tmp->next;
}
tmp->next = malloc(sizeof(struct node));
tmp->next->next = NULL;
tmp->next->data = data;
// printf("%d\n",data);
}
}
int print (struct node *head) {
printf("hello entered here\n");
struct node *tmp = head;
if (head == NULL) {
printf("entered null\n");
return;
}
while (tmp != NULL) {
if (tmp->next == NULL) {
printf("%0d", tmp->data);
} else {
printf("%0d -> ", tmp->data);
}
tmp = tmp->next;
}
printf("\n");
}
I got the following warning when i compile it
In function main:
insert.c:16: warning: passing argument 1 of insert from incompatible pointer type
insert.c:17: warning: passing argument 1 of insert from incompatible pointer type
insert.c:18: warning: passing argument 1 of insert from incompatible pointer type
insert.c:19: warning: passing argument 1 of print from incompatible pointer type
insert.c:20: warning: passing argument 1 of print from incompatible pointer type
insert.c:21: warning: passing argument 1 of print from incompatible pointer type
When i run it i will get following output
hello entered here
0 -> 5 -> 6
hello entered here
0 -> 5 -> 6
hello entered here
0 -> 5 -> 6
Please help me remove this warnings.
And can u also help me add a function to remove the node in C
What is the mistake I am doing?
Should i pass **head to the function?
Currently the functions print() and insert() expects to struct node* whereas you pass struct node **. If you want to pass a copy then drop the & in your function calls in your code.
If you want to modify the pointer head pass a pointer to pointer and modify the parameters accordingly:
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
int insert (struct node **head, int data);
int print (struct node **head);
int main()
{
struct node *head;
head = NULL;
// printf("%d\n",head);
insert(&head,5);
insert(&head,4);
insert(&head,6);
print(&head);
print(&head);
print(&head);
}
int insert(struct node **head,int data){
if(*head == NULL){
*head = malloc(sizeof(struct node));
(*head)->next = NULL;
(*head)->data = data;
// printf("%d\n",data);
}
else {
struct node *tmp = *head;
if(tmp->next!=NULL){
tmp = tmp->next;
}
tmp->next = malloc(sizeof(struct node));
tmp->next->next = NULL;
tmp->next->data = data;
// printf("%d\n",data);
}
}
int print (struct node **head) {
printf("hello entered here\n");
struct node *tmp = *head;
if (*head == NULL) {
printf("entered null\n");
return;
}
while (tmp != NULL) {
if (tmp->next == NULL) {
printf("%0d", tmp->data);
} else {
printf("%0d -> ", tmp->data);
}
tmp = tmp->next;
}
printf("\n");
}
Your insert() smells - too complicated. This is some sort of OO actually.
Here is my way, direct typed:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// class node_t
typedef struct __node_s *node_t; // Mind the pointer here.
struct __node_s {
int data;
node_t next;
};
node_t node_init(void); // Constructor.
void node_append(node_t, int);
void node_drop_last(node_t);
void node_print(node_t);
void node_fini(node_t); // Destructor.
// end class node_t
int main(void)
{
node_t head = node_init();
node_append(head, 5);
node_append(head, 4);
node_append(head, 6);
node_print(head);
node_drop_last(head);
node_print(head);
node_fini(head);
head = NULL;
return 0;
}
node_t node_init(void)
{
node_t node = malloc(sizeof(struct __node_s));
assert(node);
memset(node, 0, sizeof(struct __node_s));
return node;
}
void node_insert(node_t head, int data)
{
node_t last = head, new = node_init();
for (; last->next; last = last->next);
new->data = data;
last->next = new;
}
void node_drop_last(node_t head)
{
node_t last = head;
if (!head->next)
return;
for (; last->next->next; last - last->next);
node_fini(last->next);
last->next = NULL;
}
void node_print(node_t head)
{
for (node_t this = head->next; this; this = this->next)
{
printf("%d", this->data);
if (this->next)
putchar(' '); // A lot faster!
}
putchar('\n');
}
void node_fini(node_t head)
{
if (head->next)
{
node_fini(head->next);
head->next = NULL;
}
free(head);
}