Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I wrote this to perform push and reverse operation on linked list but the push/reverse function is not working somehow. I don't know where the problem is, everything seems to be fine. Can someone help me out? I think there's a problem with the head of the linked list or the parameter of the functions. Do I need to declare a pointer to pointer as parameter?
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
struct node {
int data;
struct node *next;
};
typedef struct node NODE;
NODE *head1 = NULL;
int flag = 1;
int choice;
void push(NODE*);
void menu();
void reverse(NODE*);
void display(NODE*);
int main() {
do {
menu();
if (choice == 1) {
push(head1);
display(head1);
}
else if (choice == 2) {
reverse(head1);
display(head1);
}
else {
break;
}
} while (1);
}
void push(NODE *head) { //function to create the linked list
int choice1, flag = 1;
do {
NODE *new_node = (NODE*)malloc(sizeof(NODE*));
puts("Enter new node data:");
scanf("%d", &new_node->data);
if (!head) {
head = new_node;
head->next = NULL;
}
else {
new_node->next = head;
head = new_node;
}
puts("Do you want to continue? Press 1:");
fflush(stdin);
scanf("%d", &choice1);
if (choice1 != 1) {
flag = 0;
}
} while (flag);
}
void menu() {
puts("Enter 1 to push, 2 to reverse, anything else to exit:");
scanf("%d", &choice);
}
void reverse(NODE *head) { //function to reverse it
NODE *prev = NULL, *next = NULL;
NODE *current = head;
while (current) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head = prev;
}
void display(NODE *head) {
NODE *temp = head;
puts("Status of the linked list:");
for (; temp; temp = temp->next) {
printf("%d=> ", temp->data);
}
puts("NULL");
}
There are many things wrong with this code. I'll start with a small snippet.
/* global */
NODE *head1 = NULL;
/* in main */
push(head1);
void push(NODE *head) { //function to create the linked list
int choice1, flag = 1;
do {
NODE *new_node = (NODE*)malloc(sizeof(NODE*));
puts("Enter new node data:");
scanf("%d", &new_node->data);
if (!head) {
head = new_node;
head->next = NULL;
}
push() is taking a pointer to NODE, allocating something and then assigning it to that pointer. this only modifies the local copy of the pointer in push() , leaving head1 unmodified. To modify head1, you either need to return a pointer or take a pointer to pointer.
That is either
void push(NODE** head)
or
NODE* push(NODE* head)
head1 = push(head1);
Also you are allocating sizeof(NODE*), the size of a pointer (typically 8 or 4 bytes). This should be sizeof(NODE).
Related
I have written a linked list program which stores data member as void *.
while trying to store annd print using scanf/printf functions, I am getting segmentation fault.
node definition -->
typedef struct node {
struct node *next;
void *data;
}node;
main function -->
head=(node *)malloc(sizeof(node));
if (head==NULL){
printf("error in allocation of memory\n");
exit(EXIT_FAILURE);
}
tail=(node*)create(head);
create function -->
void *create(node *current)
{
int user_choice;
while(current){
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
}
}
return current;
}
can anyone tell what is the correct argument for scanf & prinf should be..?
working code after incorporating points given in answers...
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
In your code,
scanf("%s",current->data);
is attempt to make use of an unitialized pointer, it invokes undefined behavior.
You need to follow either of bellow approach,
make the pointer point to valid chunk of memory (using malloc() and family for dynamic allocation, for example)
use an array.
You should first initialize data member of structure because
current->data = malloc("passes size here");
For putting data you have to typecast first this data because void is not storage type. void pointer can be used to point to any data type.
Like
*(char *)(current->data) = 1;
As others have said:
scanf("%s",current->data);
Is undefined in C. current->data needs to be pointing somewhere before you can store anything in it.
You should instead:
Accept input from scanf.
Store in temporary buffer.
Insert into linked list
print out whole linked list at the end
free() linked list at the end.
I also feel that your current void *create function is doing too much, and it would be easier to split up your code into different functions, just to make it easier to handle all the pointer operations, inserting etc.
To demonstrate these points, I wrote some code a while ago which does these things, and has been modified to help you with your code. It is not the best code, but it does use these points that will help you with your code.
Here it is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRLEN 100
typedef struct node {
void *data;
struct node *next;
} node_t;
typedef struct {
node_t *head;
node_t *foot;
} list_t;
list_t *create_list(void);
node_t *generate_node(void);
list_t *insert_node(list_t *list, char *data);
void print_list(list_t *list);
void free_list(list_t *list);
int
main(int argc, char *argv[]) {
list_t *list;
char data[MAXSTRLEN];
int user_choice;
list = create_list();
while (1) {
printf("Enter the data: ");
scanf("%s", data);
printf("\nType '1' to continue, '0' to exit:\n");
if (scanf("%d",&user_choice) != 1) {
printf("Invalid input\n");
exit(EXIT_FAILURE);
}
if (user_choice == 1) {
list = insert_node(list, data);
} else {
list = insert_node(list, data);
break;
}
}
print_list(list);
free_list(list);
list = NULL;
return 0;
}
/* inserting at foot, you can insert at the head if you wish. */
list_t
*insert_node(list_t *list, char *data) {
node_t *newnode = generate_node();
newnode->data = malloc(strlen(data)+1);
strcpy(newnode->data, data);
newnode->next = NULL;
if (list->foot == NULL) {
list->head = newnode;
list->foot = newnode;
} else {
list->foot->next = newnode;
list->foot = newnode;
}
return list;
}
node_t
*generate_node(void) {
node_t *new = malloc(sizeof(*new));
new->data = NULL;
return new;
}
void
print_list(list_t *list) {
node_t *curr = list->head;
printf("\nlinked list data:\n");
while(curr != NULL) {
printf("%s\n", (char*)curr->data);
curr = curr->next;
}
}
list_t
*create_list(void) {
list_t *list = malloc(sizeof(*list));
if (list == NULL) {
fprintf(stderr, "%s\n", "Error allocating memory");
exit(EXIT_FAILURE);
}
list->head = NULL;
list->foot = NULL;
return list;
}
void
free_list(list_t *list) {
node_t *curr, *prev;
curr = list->head;
while (curr) {
prev = curr;
curr = curr->next;
free(prev);
}
free(list);
}
UPDATE:
Also note how I allocated memory for newnode->data?
Like this:
newnode->data = malloc(strlen(data)+1); //using buffer from scanf
This now means I can store data in this pointer, your current->data will need to do something similar.
working code-->
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
Please try with this
void *create(node *current)
{
int user_choice;
while(true){
if(current == NULL) {
current = (node *)malloc(sizeof(node));
current->data = NULL;
current->next = NULL;
}
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n", (void *)current->data);
printf("%s",current->data);
//printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
tail = current;
current=current->next;
break;
}
}
return current;
}
Note: The element has to be initialized (ie; it has to be alloted with some memory) before we are trying to make use of it.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I just made a program of double linked list in which I was trying to print the values after every insertion operation done.
After first insertion no value is being printed but from the second insertion the value is printing fine(except the first one).
I am hereby attaching the full code
// Double Linked List
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next,*prev;
};
struct node *head;
struct node *getnewnode(int);
void insertathead(int);
void insertattail(int);
void display();
void rev_display();
void main()
{
char c;
int n,n1;
clrscr();
head = NULL;
do
{
printf("\n Enter Data Element");
scanf("%d", &n);
printf("Press 1 to insert at beginning \n Press 2 to insert at the end");
scanf("%d", &n1);
if(n1 == 1)
{
insertathead(n);
display();
rev_display();
}
if(n1 == 2)
{
insertattail(n);
display();
rev_display();
}
printf("Do you wish to enter more (Y/N)");
c = getch();
} while(c == 'Y' || c == 'y');
getch();
}
struct node *getnewnode(int x)
{
struct node *newnode = (struct node*)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return(newnode);
}
void insertathead(int x)
{
struct node *temp = getnewnode(x);
if(head == NULL)
{
head = temp;
}
else
{
head->prev = temp;
temp->next = head;
head = temp;
}
}
void display()
{
struct node *temp;
temp = head;
printf("Forward:\n");
while(temp->next != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
void rev_display()
{
struct node *temp;
temp = head;
while(temp->next != NULL)
{
temp = temp->next;
}
while(temp->prev != NULL)
{
printf("%d ", temp->data);
temp = temp->prev;
}
}
void insertattail(int x)
{
struct node *temp = getnewnode(x);
struct node *t;
t = head;
while(t->next != NULL)
{
t = t->next;
}
t->next = temp;
temp->prev = t;
}
The error is in the definition of the while loop. You stop when you reach a setting with no previous entry. You should stop when the current entry is NULL
Also note that in your original you call rev_display() but you defined the function as rev_dispaly(). That typo should be fixed.
You also assume that insertattail() never has a case in which the list is empty (head == NULL) I will show how that occurs after the rev_display fix.
void rev_display()
{
struct node *temp;
temp=head;
// This correctly finds the last entry
while(temp->next!=NULL)
{
temp=temp->next;
}
/* This will stop when you reach the entry with no previous entry */
while(temp->prev!=NULL)
{
printf("%d ",temp->data);
temp=temp->prev;
}
}
The code should really be
void rev_display()
{
struct node *temp;
temp=head;
// This correctly finds the last entry
while(temp->next!=NULL)
{
temp=temp->next;
}
/* This will correctly include the head as well in the print */
while(temp != NULL)
{
printf("%d ",temp->data);
temp=temp->prev;
}
}
You do not check for the empty list case in insertattail().
void insertattail(int x)
{
struct node *temp=getnewnode(x);
struct node *t;
t=head;
// Note that this assumes that the list is not empty
while(t->next!=NULL)
{
t=t->next;
}
t->next=temp;
temp->prev=t;
}
This needs to check for the empty list.
void insertattail(int x)
{
struct node *temp=getnewnode(x);
struct node *t;
// First check if the list is empty
if(head==NULL)
{
head=temp;
head->next = NULL;
head->prev = NULL;
}
else
{
t=head;
// This list is not empty so find the end
while(t->next!=NULL)
{
t=t->next;
}
t->next=temp;
temp->prev=t;
}
}
While inserting node at end in linked list ,my code is running in infinite loop.
IDE Used-Eclipse
64 bit OS
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head;
node *ptr1;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
//To insert the data in linked list
void insert(int x)
{
node *ptr;
ptr1=head;
ptr=(node*)malloc(sizeof(node));
ptr->info=x;
if(head==NULL)
{
ptr->next=head;
head=ptr;
}
else
{
ptr1->next=NULL;
ptr1=ptr;
}
}
//To print the details of list
//Unable to figure out this function
void show()
{
while(ptr1->next!=NULL)
{
printf("%d\n",ptr1->info);
ptr1=ptr1->next;
}
}
The ptr1 is set to head each time your code enters the insert function then setting it to ptr in the else subsection but nothing pointing to any previous items.
Here is an example in case you need one.
typedef struct Node
{
int info;
struct Node *next;
}node;
node *head = NULL;
void insert(int x);
void show();
int main()
{
int i,x,n;
puts("Enter number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
puts("Enter elements");
scanf("%d",&x);
insert(x);
}
show();
return 0;
}
void insert(int x)
{
node *ptr = (node*)malloc(sizeof(node));
ptr->info=x;
ptr->next=head; /* this will always add the new entry at the beginning of the list all you need it to initialize the head to NULL*/
head = ptr; /* move the head so that it points to the newly created list element */
}
void show()
{
node *ptr1 = head;
printf("%d\n",ptr1->info); /* print the head */
while(ptr1->next!=NULL) /* now walk the list remember it first looks if the next pointer in the list is null first then it jumps on next element in case it is not*/
{
ptr1=ptr1->next;
printf("%d\n",ptr1->info);
}
}
Remember to create a function to free up the list elements before exiting the main.
Your two functions can be simplified. A singly linked list is very easy to implement. I would also improve the functions by taking the list pointer as an argument, and in the case of insert() return the new head of the list: but get it working first! Note there is no reason or need to declare global variables when their only use is local to a function.
// insert new node at head of the list
void insert(int x) {
node *ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = head; // append existing list
head = ptr; // new head of list
}
// show the linked list
void show() {
node *ptr = head; // start at head of list
while (ptr != NULL) {
printf("%d\n", ptr->info);
ptr = ptr->next; // follow the link chain
}
}
EDIT here is code to add to the tail of a linked list
// insert new node at tail of the list
void insert2(int x) {
node *tail = head;
node **last = &head;
node *ptr;
while (tail) {
last = &tail->next;
tail = tail->next;
}
ptr = malloc(sizeof(node));
if (ptr == NULL) {
printf ("malloc failure\n");
exit (1);
}
ptr->info = x;
ptr->next = NULL;
*last = ptr;
}
I have this homework that asks me to make a stack using dynamic allocation and add some different functions in it. Now, usually I would use the head pointer as global variable and make things easier for me, but the homework demands that I give the head pointer to the function as an argument, so I made it local variable in main. This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node * next;
} node;
void push(int val, node *head) {
node* temp = (node*) malloc(sizeof(node));
node* current = head;
temp->val = val;
if (head == NULL) {
head = temp;
temp->next = NULL;
}
else {
while (current->next != NULL) {
current = current->next;
}
current->next = temp;
temp->next = NULL;
}
}
void print(node *head) {
node* current = head;
if (current->next != NULL) {
while (current->next != NULL) {
printf("%d", current->val);
current = current->next;
}
}
else {
printf("%d", current->val);
}
}
int main() {
node * head = NULL;
int n;
scanf("%d", &n);
push(n, head);
print(head);
push(n, head);
print(head);
push(n, head);
print(head);
}
I get a segmentation fault error at the first print(head) function that says print(head = 0x0), which made me believe that head does not update when it returns in main. I used a printf() for head after the first push function and I was right, head returns 0. Question is: How do I return the updated head in the function?
You could either declare your function like
void push(int val, node **head)
then pass a reference of your head and modify it
or
node *push(int val, node *head)
and return the new head.
Here is a program it is working
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next, *prev;
};
struct node *root = NULL;
void push(int);
void pop(void);
struct node *create_node(int);
void travel(void);
int main()
{
int i, j, choice, count;
printf("enter choice\n");
scanf("%d", &choice);
count = 0;
while (choice == 1) {
printf("enter a data element");
scanf("%d", &j);
if (count == 0) {
root = (struct node *)malloc(sizeof(struct node));
root->next = NULL;
root->data = j;
} else
push(j);
count++;
printf("enter choice\n");
scanf("%d", &choice);
}
printf("the link list is \n");
//travel function to be created
travel();
}
void push(int data)
{
struct node *t1;
t1 = root;
while (t1->next != NULL) {
t1 = t1->next;
}
t1->next = create_node(data);
}
void pop()
{
}
void travel(void)
{
struct node *t1;
t1 = root;
while (t1->next != NULL) {
printf("%d ", t1->data);
t1 = t1->next;
}
printf("%d ", t1->data);
}
struct node *create_node(int data)
{
struct node *p = (struct node *)malloc(sizeof(struct node));
p->data = data;
p->next = NULL;
p->prev = NULL;
return p;
}
the above program is fully working,I have used a global pointer root.
My problem is if I do not want to use a global pointer root here then how do I maintain
that list because each time I will have to return the root of list in my push pop functions
is there any other way to achieve the same?
The simplest way to achieve this is to pass a pointer to the root node pointer to each of your functions:
void push(struct node **root, int data) { ... }
void pop(struct node **root) { ... }
void travel(struct node *root) { ... }
So, in your main function you might declare a local variable to hold the root pointer:
struct node *root = NULL;
and then when you call push, for example, you pass the address of the root poiner:
push(&root, data);
I strongly recommend that you fix your push and travel functions so that they are robust to the root pointer being NULL. This was discussed in a previous question of yours and you should heed the advice.
If you did that then you could get rid of the test for count being zero and the associated special case code. You would then replace this:
if (count == 0) {
root = (struct node *)malloc(sizeof(struct node));
root->next = NULL;
root->data = j;
} else
push(&root, j);
with this:
push(&root, j);
To drive home the message, your new push would look like this:
void push(struct node **root, int data)
{
if (*root == NULL)
*root = create_node(data);
else
{
struct node *last = *root;
while (last->next != NULL) {
last = last->next;
}
last->next = create_node(data);
}
}
You would need to modify travel also to include a check for the root node being NULL. I will leave that as an exercise for you.
Maintaining both head and tail pointers could be a better approach since it would avoid so many list traversals.