I created a standard linked list in C. It asks the user to input a number, and program end if user input #. If the user inputs anything else the program will stop.
The problem is that my program runs forever and prints the normal list at first then keeping print the last element of the linked list.
Hope someone could tell me where did I made mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *list) {
NodeT *p, *temp;
p = list;
while (p != NULL) {
temp = p->next;
free(p);
p = temp;
}
}
void showLL(NodeT *list) {
NodeT *temp = list;
temp = temp->next;
printf("Done. The list is ");
printf("%d", temp->data);
temp = temp->next;
//iterate the entire linked list and print the data
while (temp != NULL) {
printf("-->");
printf("%d", temp->data);
temp = temp->next;
}
}
NodeT *joinLL(NodeT *list, int v) {
NodeT *current = list;
NodeT *head;
head->data = v;
head->next = NULL;
while (current->next != NULL) {
current = current->next;
}
current->next = head;
return head;
}
int main() {
int data;
NodeT *list = NULL;
list = (NodeT *)malloc(sizeof(NodeT));
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
} else {
printf("Enter a number: ");
joinLL(list, data);
while (1 == scanf("%d", &data)) {
printf("Enter a number: ");
joinLL(list, data);
}
showLL(list);
freeLL(list);
}
return 0;
}
I believe the problem is in the joinLL function which add a new node at the end of the linked list.
The problem is you do not allocate elements in joinLL: only a single element in allocated in main().
You should instead always allocate the element in joinLL and update the head pointer from the return value.
Similary, freeLL should take a pointer to head and set it to NULL for consistency.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *p) {
while (p != NULL) {
NodeT *temp = p->next;
free(p);
p = temp;
}
}
void showLL(const NodeT *list) {
NodeT *p = list;
printf("The list is ");
if (p == NULL) {
printf("empty");
} else {
printf(" %d", temp->data);
while ((p = p->next) != NULL) {
printf("--> %d", temp->data);
}
}
printf("\n");
}
NodeT *joinLL(NodeT *head, int v) {
NodeT *newp = malloc(sizeof(*p));
NodeT *current;
if (newp == NULL) {
fprintf(stderr, "allocation failure\n");
exit(1);
}
newp->data = v;
newp->next = NULL;
if (head == NULL) {
return newp;
}
for (current = head; current->next != NULL; current = current->next)
continue;
current->next = newp;
return head;
}
int main() {
NodeT *list = NULL;
for (;;) {
int data;
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
break;
}
list = joinLL(list, data);
}
showLL(list);
freeLL(list);
return 0;
}
Your program keeps running because of a memory access error, you did not allocate memory for your head(you set a pointer, but use it directly without initializing it)
Change to this may solve the problem:
head=(NodeT*)malloc(sizeof(NodeT));
if(NULL==head)
{
// failed : do something...
return NULL;
}
head->data=v;
head->next=NULL;
When I just tested it, I found that there was another problem:
list = (NodeT*)malloc(sizeof(NodeT));
malloc will not be initialize your list, so the value that your list->next initially points to is uncertain.
in c, malloc does not need to be cast.
Related
im starting to learn data structures and i tried to making a simple program about a single linked list.
The problem is that when i call my display function (transversing the list) it doesn't give me an output? What is wrong with my code and how do i fix this?
This my program:
int main(){
int n;
printf(" Input the number of nodes : ");
scanf("%d", &n);
create(n);
printf("\n Data entered in the list : \n");
display();
}
void create(int n)
{
struct node *head=NULL;
int data, i;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL)
{
printf(" Memory can not be allocated.");
}
else
{
printf(" Input data for node 1 : ");
scanf("%d", &data);
head->data = data;
head->next = NULL;
for(i=1; i<n; i++) // Creating n nodes
{
struct node *current = (struct node *)malloc(sizeof(struct node)); // addnode
if(current == NULL)
{
printf(" Memory can not be allocated.");
break;
}
else
{
printf(" Input data for node %d : ", i);
scanf(" %d", &data);
current->data = data;
current->next = NULL;
head->next = current;
head = head->next;
}
}
}
}
My Traversing function:
void display(struct node *head)
{
struct node* ptr = head;
if(head == NULL)
{
printf(" List is empty.");
}
else
{
while(ptr != NULL)
{
printf(" Data = %d\n", ptr->data);
ptr = ptr->next;
}
}
}
The problem are lines in create()
head->next = current;
head = head->next;
this operation set head to current. Note that current->next is NULL. As result the entire content of the list is lost except the last element.
Just replace those lines with:
current->next = head;
head = current;
This will put the current node at the top of the list.
Remember to return head from create().
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * next;
};
struct node * create(int n) {
struct node *head=NULL;
int data, i;
struct node * ptmp = NULL;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL) {
printf(" Memory can not be allocated.");
} else {
printf(" Input data for node 1 : ");
scanf("%d", &data);
head->data = data;
head->next = NULL;
ptmp = head;
for(i=1; i<n; i++) {
struct node *current = (struct node *)malloc(sizeof(struct node)); // addnode
if(current == NULL) {
printf(" Memory can not be allocated.");
break;
} else {
printf(" Input data for node %d : ", i);
scanf(" %d", &data);
#if 0
// insert first
current->data = data;
current->next = head;
head = current;
#else
// insrt last
current->data = data;
current->next = NULL;
ptmp->next=current;
ptmp = current;
#endif
}
}
}
return head;
}
void display(struct node *head)
{
struct node* ptr = head;
if(head == NULL) {
printf(" List is empty.");
} else {
while(ptr != NULL) {
printf(" Data = %d\n", ptr->data);
ptr = ptr->next;
}
}
}
int main() {
int n = 0;
printf(" Input the number of nodes : ");
scanf("%d", &n);
if (n<=0 || n > 6400) {
printf("Invalid input : %d (Enter value in range 0-6400)\n", n);
return 0;
}
struct node * head = create(n);
printf("\n Data entered in the list : \n");
display(head);
}
Im currently trying to make an algorithm that creates a single linked list, and sorts it in ascending order (user input n and numbers).
I can create the list fine, but when i try to swap 2 nodes value, it gives exits, segmentation fault.
I have a strong feeling it has to do with my dynamically allocated memory for the nodes, but im very new to programming, so i could use any help locating the fault
#include <stdio.h>
#include <stdlib.h>
struct node {
int val;
struct node *next;
}*node_st;
void createlist (int n) {
struct node *fnNode, *temp;
int i, num;
node_st = (struct node *)malloc(sizeof(struct node));
if (node_st == NULL) {
printf("Memory allocation fault!");
exit(0);
}
else {
printf("Input data for node 1:");
scanf("%d",&num);
node_st->val =num;
node_st->next = NULL;
temp = node_st;
for (i=2;i<=n;i++) {
fnNode = (struct node *)malloc(sizeof(struct node));
if (fnNode == NULL) {
printf("Memory allocation fault!");
break;
}
else {
printf("input data for node %d : ", i);
scanf("%d",&num);
fnNode->val = num;
fnNode->next = NULL;
temp->next = fnNode;
temp = temp->next;
}
}
}
}
void showlist() {
struct node *temp;
if (node_st == NULL) {
printf("List is empty..");
}
else {
temp = node_st;
while (temp != NULL) {
printf("Value = %d \n",temp->val);
temp = temp->next;
}
}
}
void sort(int n) {
struct node *temp;
struct node *temp2;
if (node_st == NULL) {
printf("List is empty..");
}
else {
temp = node_st;
temp2 = temp->next;
while (temp != NULL) {
if (temp->val > temp2->val) {
printf("test!!!");
temp = temp2;
temp2 = temp->next;
}
}
}
}
int main(void) {
int n,a,x,y,z;
printf("Input amount of nodes you want");
scanf("%d",&n);
createlist(n);
printf("Data entered: \n");
showlist();
sort(n);
return 0;
}
aplogize in advance for the messy code, again im new and havent cleaned it up 100%.
The purpose of this code is to manage insertion and deletion and visualisation. I just want to know if I'm doing everything correctly, let me know if there are more possible ways to do this. This is my first attempt, i didn't follow any tutorial.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int n;
struct Node *next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(Node *pp, int n)
{
Node temp, last;
temp = (Node)malloc(sizeof(struct Node));
temp->n = n;
temp->next = temp;
temp->prev = temp;
if(*pp != NULL)
{
last = (*pp)->prev;
temp->next = (*pp);
temp->prev = last;
last->next = (*pp)->prev = temp;
}
*pp = temp;
}
void ViewList(Node head)
{
if(head == NULL)
{
return;
}
Node node = head->prev;
do
{
printf("Curr: %d\n", node->n);
node = node->prev;
}while(node != head->prev);
}
void ReadData(Node * head, int * n)
{
printf("\nInsert a number:");
scanf("%d", n);
NewNode(head, *n);
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->n == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del && del->next == *head)
{
*head = NULL;
free(del);
return;
}
if(*head == del)
{
*head = del->next;
del->prev->next = *head;
(*head)->prev = del->prev;
free(del);
return;
}
if((*head)->prev == del)
{
(*head)->prev = del->prev;
del->prev->next = *head;
free(del);
return;
}
del->next->prev = del->prev;
del->prev->next = del->next;
free(del);
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c,n;
Node head = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadData(&head, &n); break;
case 2: ViewList(head); break;
case 3: Delete(&head); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
How can i test if this is a real circular doubly linked list and not a simple doubly linked list?
Your program works fine, the only real bug I detected is in SearchNode: if the element is not present in the list, you enter an infinite loop. Your list is obviously a circular list and therefore you need to check if you have got back to the head in the function, which means that the element you're searching for is not in the list:
Corrected version:
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
Node start = head; // remember where we started
while (head != NULL)
{
if (head->n == d)
{
return head;
}
head = head->next;
if (head == start) // if we are back to where we started
break; // the element hasn't been found and we stop the loop
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
There are also some design flaws, that don't prevent the program from working correctly:
One of them is this: The n variable is not used outside ReadData, so it's pointless to declare it in main and pass it's pointer to ReadData.
Corrected version:
void ReadData(Node * head)
{
int n; // declare n locally
printf("\nInsert a number:");
scanf("%d", &n);
NewNode(head, n);
}
Call it like this: ReadData(&head) and remove int n; from main.
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.
So I'm having trouble getting my program to print both the strings I input, or however many you want to put in the list, it always prints out the last string inputted multiple times. I am sorry about all the commented out code, most of it you don't need to read.
#include<stdio.h>
#include<stdlib.h>
struct node{
char *data;
struct node *next;
}*head;
typedef struct node NODE;
// Function prototypes
void append(char myStr[]);
void add( char myStr[] );
//void addafter(char myStr[], int loc);
void insert(char myStr[]);
int delete(char myStr[]);
void display(struct node *r);
int count();
// main function
int main()
{
int i;
struct node *n;
head = NULL;
char myStr[50];
while(1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Size\n");
printf("4.Delete\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if(scanf("%d", &i) <= 0)
{
printf("Enter only an Integer\n");
exit(0);
}
else
{
switch(i)
{
case 1:
printf("Enter the name to insert : ");
scanf("%50s", myStr);
insert(myStr);
break;
case 2:
if(head == NULL)
{
printf("List is Empty\n");
}
else
{
printf("Name(s) in the list are : ");
}
display(n);
break;
case 3:
printf("Size of the list is %d\n",count());
break;
case 4:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the myStrber to delete : ");
scanf("%50s",myStr);
if(delete(myStr))
printf("%s deleted successfully\n",myStr);
else
printf("%s not found in the list\n",myStr);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
// Function definitions
void append(char myStr[])
{
struct node *temp,*right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = myStr;
right=(struct node *)head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
right = temp;
right->next = NULL;
}
// adding a node to the beginning of the linked list
void add( char myStr[] )
{
struct node *temp;
temp =(struct node *)malloc(sizeof(struct node));
temp->data = myStr;
// only one node on the linked list
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void insert(char myStr[])
{
int c = 0;
struct node *temp;
temp = head;
if(temp == NULL)
{
add(myStr);
}
else
{
append(myStr);
}
}
int delete(char myStr[])
{
struct node *temp, *prev;
temp = head;
while(temp != NULL)
{
if(temp->data == myStr)
{
if(temp == head)
{
head = temp->next;
head = (*temp).next;
free(temp);
return 1;
}
else
{
prev->next = temp->next;
free(temp);
return 1;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return 0;
}
void display(struct node *r)
{
r = head;
if(r == NULL)
{
return;
}
while(r != NULL)
{
printf("%s ", r->data);
r = r->next;
if(r == NULL)
{
printf("\nOur linked list is finished!");
}
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while(n != NULL)
{
n = n->next;
c++;
}
return c;
}
The problem seems to be that myStr at main function is a char[], so it's content is overritten every time you insert data. Notice that struct node data field is a char*, it's just pointing to myStr address.
Hope this help!
Your program has only one place to write your input, myStr.
With each input, myStr is erased and a something else is written to myStr.
The data member of all of the nodes, points to myStr. myStr will only contain the last input.
The display() function asks each node what is data. data points to myStr so each node prints the contents of myStr. myStr will only contain the last input so all the nodes print the last input.
To fix this, in the add() and append() functions, you need to give the data member some memory by using malloc(). Then copy the contents of myStr to the data member by using strcpy().
temp->data = malloc ( strlen ( myStr) + 1);
strcpy ( temp->data, myStr);
Do this instead of temp->data = myStr;
You will need #include<string.h>
The memory will need to be free()'d in the delete() function.
free(temp->data);
Do this before freeing temp
char *data
that variable from struct is always assigned with the address of myStr as its a pointer it would only show you the value of myStr