How to make this list a circular list? - c

The code is the next, I would like for the last item in the list to aim with a pointer to the beginning of the list all the time, even if I change it or remove it, but I don know how. I'm kind of new to this.
This is the full code I have, with functions to insert and remove the elements in the list as well with a function for instructions and to print
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
struct listNode {
char data;
struct listNode *nextPtr;
};
typedef struct listNode LISTNODE;
typedef LISTNODE *LISTNODEPTR;
char delete(LISTNODEPTR *, char);
int isEmpty(LISTNODEPTR);
void printList(LISTNODEPTR);
void instructions(void);
LISTNODE *addtoList(LISTNODEPTR *sPtr, char value);
int main() {
LISTNODEPTR startPtr = NULL;
int choice;
char item;
instructions();
printf("? ");
scanf("%d", &choice);
while (choice != 3) {
switch (choice) {
case 1:
printf("Enter a character: ");
scanf("\n%c", &item);
insert(&startPtr, item);
printList(startPtr);
break;
case 2:
if (!isEmpty(startPtr)) {
printf("Enter character to be deleted: ");
scanf("\n%c", &item);
if (delete (&startPtr, item)) {
printf("%c deleted.\n", item);
printList(startPtr);
} else
printf(
"List is empty or the element doesn´t exist.\n\n");
break;
default:
printf("Invalid choice.\n\n");
instructions();
break;
}
}
printf("? ");
scanf("%d", &choice);
}
printf("End of run.\n");
return 0;
}
void instructions(void) {
printf(
"Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to end.\n");
}
char delete(LISTNODEPTR *sPtr, char value) {
LISTNODEPTR previousPtr, currentPtr, tempPtr;
// if (value == (*sPtr)->data){
if (value == (*sPtr)->data) {
tempPtr = *sPtr;
*sPtr = (*sPtr)->nextPtr;
free(tempPtr);
return value;
} else {
previousPtr = *sPtr;
currentPtr = (*sPtr)->nextPtr;
while (currentPtr != NULL && currentPtr->data != value) {
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if (currentPtr != NULL) {
tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free(tempPtr);
return value;
}
}
return '\0';
}
int isEmpty(LISTNODEPTR sPtr) { return sPtr == NULL; }
void printList(LISTNODEPTR currentPtr)
{
if (currentPtr == NULL) printf("List is empty. \n\n");
while (currentPtr != NULL) {
printf("%p %c -->", currentPtr, currentPtr->data);
currentPtr = currentPtr->nextPtr;
}
printf("NULL\n\n");
}
LISTNODE *addtoList(LISTNODE *sPtr, char value)
{
LISTNODE* temp = malloc(sizeof(LISTNODE));
if(temp == NULL)
{
printf("%d not inserted. No memory available.\n", value);
exit(0);
}
else
{
temp->data = value;
temp->nextPtr = NULL;
}
if(sPtr == NULL)
{
sPtr = temp;
return sPtr;
}
else
if(sPtr != NULL && sPtr->nextPtr == NULL)
{
sPtr->nextPtr = temp;
return sPtr;
}
else
if (sPtr != NULL && sPtr->nextPtr != NULL)
{
LISTNODE* Head = sPtr;
while(Head->nextPtr != NULL)
{
Head = Head->nextPtr;
}
Head->nextPtr = temp;
return sPtr;
}
else
{
printf("Unknown state of List\n\n");
exit(0);
}
}

With a circular list keeping track of the tail seems to have the fewest special cases and allows insertion at the front or back and deletion of the front in O(1). Deleting a node requires getting hold of their previous node. So iteration is best done with a pointer to the previous node kept in store.
So I made 2 structs: A ListNode that holds a pointer to the next node and the data. And a List that holds a pointer to the tail of the list. Although what the tail is in a circular list is arbitrary.
Operations on lists are always done by passing a List * in case the List.tail has to be updated. Operations that do not change the list take a const List *, e.g. printList().
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct ListNode
{
struct ListNode *next;
char data;
} ListNode;
typedef struct List
{
ListNode *tail;
} List;
bool isEmpty(const List *list)
{
return list->tail == NULL;
}
void printList(const List *list)
{
if (isEmpty(list)) {
printf("List is empty.\n\n");
return;
}
// iteration works by keeping a pointer to the previous node
// so we start at the tail to print the first node
// it ends when the tail has been visited
ListNode *p = list->tail;
do {
p = p->next;
printf("%p %c -->", p, p->data);
} while(p != list->tail);
printf("\n\n");
}
char delete(List *list, char value)
{
if (isEmpty(list)) return '\0';
ListNode *p = list->tail;
do {
ListNode *q = p->next;
if (q->data == value) {
// remove q from list
p->next = q->next;
// are we removing the last node?
if (p == q) list->tail = NULL;
// if q is the tail set the tail to the previous node
if (list->tail == q) list->tail = p;
free(q);
return value;
}
p = q;
} while(p != list->tail);
return '\0';
}
// add value to the end of the list
void insert(List *list, char value)
{
// allocate node
ListNode *node = malloc(sizeof(ListNode));
if (node == NULL)
{
printf("'%c' not inserted. No memory available.\n", value);
exit(0);
}
node->data = value;
// if list is empty point the tail at the new node
if (isEmpty(list)) {
list->tail = node;
}
// point the node at the head of the list
node->next = list->tail->next;
// point the tail node at the new node
list->tail->next = node;
// update the tail to the new node
list->tail = node;
}
void instructions(void);
int main() {
List list = { NULL };
int choice;
char item;
instructions();
do {
printf("? ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter a character: ");
scanf("\n%c", &item);
insert(&list, item);
printList(&list);
break;
case 2:
if (!isEmpty(&list)) {
printf("Enter character to be deleted: ");
scanf("\n%c", &item);
if (delete (&list, item)) {
printf("'%c' deleted from list.\n", item);
printList(&list);
} else {
printf("'%c' not found in list.\n", item);
}
} else {
printf("List is empty.\n\n");
}
break;
case 3:
break;
default:
printf("Invalid choice.\n\n");
instructions();
break;
}
} while (choice != 3);
printf("End of run.\n");
return 0;
}
void instructions(void)
{
printf(
"Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to end.\n");
}

Related

Abnormal behavior of function in Singly Linked list program

Few days back I made a Singly Linked list Implementation Program using C with operations - insertion at front, insertion at back , deletion at back , deletion at front and display which was working fine.
Yesterday I made another program to insert a node at certain position in singly linked list adding extra function - insertion at position , and rest functions were copied from previous code which were working fine in previous program. Now when I was performing operations on old functions in new programs which were working fine in old program , they were showing abnormal behaviour.
Note:
I am getting error in old functions not new function.
Old Program is Running Fine
Error: when I am using inserting two or more values in linked list using either of function - insertion at front or insertion at back and then using display function. Infinite loop is running
//Program Which was working fine
//Linked List Implementation
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *link;
}node;
void add_front(node **head)
{
int value;
if((*head) == NULL)
{
*head = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
(*head)->data = value;
(*head)->link = NULL;
}
else
{
node *temp;
temp = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = *head;
*head = temp;
free(temp);
}
}
void add_end(node **head)
{
int value;
if((*head) == NULL)
{
*head = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
(*head)->data = value;
(*head)->link = NULL;
}
else
{
node * temp = malloc(sizeof(node));
node * ptr = *head;
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = NULL;
while(ptr->link != NULL)
{
ptr = ptr->link;
}
ptr->link = temp;
free(temp);
free(ptr);
}
}
void del_front(node **head)
{
if((*head) != NULL)
{
node *temp;
temp = *head;
printf("Value of deleted node is %d \n",(*head)->data);
*head = (*head)->link;
free(temp);
}
else
{
printf("Linked list is Empty...\n");
}
}
node *del_end(node *head)
{
if(head == NULL)
{
printf("Linked List is Empty...\n");
return NULL;
}
else if (head->link == NULL)
{
printf("Value of deleted node is %d\n",head->data);
free(head);
head = NULL;
return head;
}
else
{
node * ptr1 = head;
node * ptr2 = NULL;
while(ptr1->link != NULL)
{
ptr2 = ptr1;
ptr1 = ptr1->link;
}
printf("Value of deleted node is %d\n",ptr1->data);
free(ptr2->link);
ptr2->link = NULL;
return head;
free(ptr1);
free(ptr2);
}
}
void display(node *head)
{
if(head == NULL)
{
printf("Linked List is Empty...\n");
}
else
{
while(head != NULL)
{
printf("%d ",head->data);
head = head->link;
}
printf("\n");
}
}
int main()
{
node *head = NULL;
int choice;
printf("Linked list Implementation...\n\n");
printf("Enter \n1. To add next node at beginning of the linked list\n");
printf("2. To add next node at end of the linked list\n");
printf("3. To delete first node\n");
printf("4. To delete last node\n");
printf("5. To display the linked list\n");
printf("6.Exit\n");
do
{
printf("Enter your choice: \n");
scanf("%d",&choice);
switch(choice)
{
case 1:
add_front(&head);
break;
case 2:
add_end(&head);
break;
case 3:
del_front(&head);
break;
case 4:
head = del_end(head);
break;
case 5:
display(head);
break;
case 6:
printf("Exiting...\n");
break;
default:
printf("Wrong Choice...\n");
}
}while(choice!=6);
free(head);
return 0;
}
//program having error
// inserting a node at a given position in singly linked list
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *link;
}node;
void add_front(node **head)
{
int value;
if((*head) == NULL)
{
*head = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
(*head)->data = value;
(*head)->link = NULL;
}
else
{
node *temp;
temp = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = *head;
*head = temp;
free(temp);
}
}
void add_end(node **head)
{
int value;
if((*head) == NULL)
{
*head = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
(*head)->data = value;
(*head)->link = NULL;
}
else
{
node * temp = malloc(sizeof(node));
node * ptr = *head;
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = NULL;
while(ptr->link != NULL)
{
ptr = ptr->link;
}
ptr->link = temp;
free(temp);
free(ptr);
}
}
void del_front(node **head)
{
if((*head) != NULL)
{
node *temp;
temp = *head;
printf("Value of deleted node is %d \n",(*head)->data);
*head = (*head)->link;
free(temp);
}
else
{
printf("Linked list is Empty...\n");
}
}
node *del_end(node *head)
{
if(head == NULL)
{
printf("Linked List is Empty...\n");
return NULL;
}
else if (head->link == NULL)
{
printf("Value of deleted node is %d\n",head->data);
free(head);
head = NULL;
return head;
}
else
{
node * ptr1 = head;
node * ptr2 = NULL;
while(ptr1->link != NULL)
{
ptr2 = ptr1;
ptr1 = ptr1->link;
}
printf("Value of deleted node is %d\n",ptr1->data);
free(ptr2->link);
ptr2->link = NULL;
return head;
free(ptr1);
free(ptr2);
}
}
node *insert_pos(node *head)
{
if(head == NULL)
{
printf("Linked List is Empty...\n");
return;
}
int pos;
node *temp = malloc(sizeof(node));
printf("Enter the position to insert new node : ");
scanf("%d",&pos);
if(pos == 1)
{
printf("Enter the value to insert : ");
scanf("%d",&(temp->data));
temp->link = head;
head = temp;
return head;
}
int n = 1;
while(pos!=2)
{
if(head->link == NULL)
{
printf("Linked List has only %d node\n",n);
return;
}
head = head->link;
n++;
pos--;
}
node *ptr = malloc(sizeof(node));
ptr = head->link;
printf("Enter the value to insert : ");
scanf("%d",&(temp->data));
head->link = temp;
temp->link = ptr;
free(ptr);
}
node *delete_pos(node *head)
{
return;
}
void display(node *head)
{
if(head == NULL)
{
printf("Linked List is Empty...\n");
}
else
{
while(head != NULL)
{
printf("%d ",head->data);
head = head->link;
}
printf("\n");
}
}
int main()
{
node *head = NULL;
int choice;
printf("Linked list Implementation...\n\n");
printf("Enter \n1. To add next node at beginning of the linked list\n");
printf("2. To add next node at end of the linked list\n");
printf("3. To delete first node\n");
printf("4. To delete last node\n");
printf("5. To insert a node at certain position\n");
printf("6. To delete a node at certain position\n");
printf("7. To display the linked list\n");
printf("8.Exit\n");
do
{
printf("Enter your choice: \n");
scanf("%d",&choice);
switch(choice)
{
case 1:
add_front(&head);
break;
case 2:
add_end(&head);
break;
case 3:
del_front(&head);
break;
case 4:
head = del_end(head);
break;
case 5:
head = insert_pos(head);
break;
case 6:
delete_pos(head);
break;
case 7:
display(head);
break;
case 8:
printf("Exiting...\n");
break;
default:
printf("Wrong Choice...\n");
}
}while(choice!=8);
free(head);
return 0;
}
There is already undefined behavior in the first function add_front in this code snippet
else
{
node *temp;
temp = malloc(sizeof(node));
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = *head;
*head = temp;
free(temp);
^^^^^^^^^^
}
You deleted the node that was added in the list.
And the function add_front has duplicated code.
The same problem exist with the function add_end In this function you decided to delete even two valid nodes.:)
else
{
node * temp = malloc(sizeof(node));
node * ptr = *head;
printf("Enter the value to insert : ");
scanf("%d",&value);
temp->data = value;
temp->link = NULL;
while(ptr->link != NULL)
{
ptr = ptr->link;
}
ptr->link = temp;
free(temp);
^^^^^^^^^^
free(ptr);
^^^^^^^^^
}
You shall not delete nodes in these functions.
In the function del_end the code after the return statement never gets the control and must be removed.
printf("Value of deleted node is %d\n",ptr1->data);
free(ptr2->link);
ptr2->link = NULL;
return head;
free(ptr1); // <===
free(ptr2); // <===
If you want to add and delete nodes at the end of the list then you should declare a tw-sided singly-linked list.

How to delete nodes in a doubly linked list

I'm having trouble deleting nodes in a doubly linked list, the program crash and i can't figure out the problem. Can you please help me?
This is the full code that creates new nodes, views them and deletes them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
void Delete(Node * head, Node del)
{
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("*** 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;
struct Test test;
Node list = NULL;
Node del = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: printf("\nElement to Delete: ");
scanf("%d", &del->structure.id);
Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
I think the problem is related to the scanf() for the Node del, but i'm not sure. When i just pass list or list->next as second argument to the function Delete() it works. Is everything all right with the code?
int main()
{
...
Node del = NULL;
...
scanf("%d", &del->structure.id);
Your program should crash here. You are dereferencing a null pointer.
Probably you will need to read the user input into a temporary id variable, then search the list for a matching item, and if you find one, then you can try deleting it.
Ok, i added a function that searches for the node to be deleted and i modified a bit the Delete() function, this is the workaround, thank you for the suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->structure.id == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head, struct Test temp)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
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;
struct Test test, del;
Node list = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
del value is NULL, but you reference it when you delete.
What you need is to search a node in the list for the givent id and then delete it.

Error in 'exec': double free or corruption (fasttop) : 0x00000000021a2c80

I am trying to build a program using switch to manipulate linked lists of characters, but I get this error:
*** Error in `exec': double free or corruption (fasttop): 0x00000000021a2c80 ***
======= Backtrace: =========
[0x40a467]
[0x40fcf2]
[0x41050e]
[0x400c20]
[0x400e8f]
[0x401123]
[0x4013ae]
[0x4009ba]
I know that this error is something about the allocation and deallocation but I have literally checked the code for more than 3 hrs and I cannot see the mistake, can any of you who are professionals help me or guide me to find the error?
Here is my complete code:
#include <stdio.h>
#include <stdlib.h>
struct list
{
struct list *prev;
char info;
struct list *next;
};
struct list* push_front(struct list *my_list, char value )
{
struct list *newel;
newel = (struct list*) malloc(sizeof(struct list));
if (newel == NULL)
{
printf("Error allocating memory\n");
exit(1);
}
newel->info = value;
newel->next = my_list;
newel -> prev = NULL;
if (my_list!=NULL)
{
my_list -> prev = newel;
}
return newel;
}
struct list* remove_elem(struct list *my_list, char value)
{
struct list *cursor , *nex, *prv;
int x = 0;
cursor = my_list;
if (cursor==NULL)
{
printf("The element is not in the list!\n");
return my_list;
}
else if (cursor->next==NULL)
{
if (value==cursor->info)
return NULL;
else
{
printf("The element is not in the list!\n");
return my_list;
}
}
else
{
while (cursor->next!=NULL)
{
if (cursor->info==value)
{
if (cursor->prev==NULL)
{
cursor=cursor->next;
free(cursor->prev);
cursor->prev=NULL;
my_list=cursor;
}
else
{
nex=cursor->next;
prv=cursor->prev;
prv->next=nex;
nex->prev=prv;
free(cursor);
}
x=1;
}
else
cursor=cursor->next;
}
if (cursor->info==value)
{
if (cursor->prev!=NULL)
{
cursor->prev->next=NULL;
free(cursor);
x=1;
}
else
{
x=1;
cursor=NULL;
my_list=NULL;
}
}
if (x==1)
return my_list;
else
{
printf("The element is not in the list!\n");
return my_list;
}
}
}
void print(struct list *my_list)
{
struct list *ptr;
ptr = my_list;
while (ptr != NULL)
{
printf("%c ", ptr->info);
ptr = ptr->next;
}
printf("\n");
}
void rev(struct list *my_list)
{
struct list *ptr;
ptr = my_list;
if (ptr!=NULL)
{
while (ptr -> next != NULL)
ptr = ptr -> next;
while (ptr != NULL)
{
printf("%c ",ptr -> info);
ptr = ptr -> prev;
}
}
printf("\n");
}
struct list *dispose_list(struct list* my_list)
{
struct list *removedList;
struct list *returnlist;
if (my_list == NULL)
{
return 0;
}else
{
removedList = my_list->next;
my_list = removedList;
returnlist = my_list;
}
return returnlist;
}
char readChar()
{
char c;
do
{
scanf("%c", &c);
}while (c == ' ' || c == '\n');
return c;
}
int main()
{
struct list* new_list = NULL;
int nr;
char ch;
while (nr != 5)
{
scanf("%d", &nr);
switch (nr)
{
case 1:
ch = readChar();
new_list = push_front(new_list, ch);
break;
case 2:
ch = readChar();
new_list = remove_elem(new_list, ch);
break;
case 3:
print(new_list);
//printf("\n");
break;
case 4:
rev(new_list);
//printf("\n");
break;
case 5:
exit(1);
break;
}
}
dispose_list(new_list);
return 0;
}
I'd go through the list and check if the current node's info is the same as the
value. If that's the case, remove the node, update the prev and next
pointers around the current node, free the node and move to the next one. Stop
when NULL has reached. If the current's node prev is NULL, then we have to
update the head as well by setting my_list. The function returns the new
head of the list or NULL when the list is empty or when all nodes of the list
were removed. This is my version:
struct list* remove_elem(struct list *my_list, char value)
{
int removed_something = 0;
struct list *current = my_list, *tofree;
while(current)
{
if(current->info == value)
{
if(current->next)
current->next->prev = current->prev;
if(current->prev)
current->prev->next = current->next;
else
my_list = current->next; // update head of list
tofree = current;
current = current->next;
free(tofree);
removed_something = 1;
} else
current = current->next;
}
if(removed_something == 0)
fprintf(stderr, "Node with value '%c' not found\n", value);
return my_list;
}
I don't do while(current->next) because at the end of the loop I would have to
repeat the code in the loop for the last element of the list. By using
while(element) I reach all elements of the list inside the loop and don't
have to repeat the removing code after the loop, which is causing you trouble.
I also don't understand what your dispose_list function does. You are just
removing the head but you are not freeing the head and you are returing the rest
of the list. You also are not updating the prev pointer of the new head. This
seems all strange to me. If you want to dispose of the head:
struct list *dispose_list(struct list* my_list)
{
if(my_list == NULL)
return NULL;
struct list *oldhead = my_list;
my_list = my_list->next;
if(my_list)
my_list->prev = NULL;
free(oldhead);
return my_list;
}
And if you want to free the whole list:
void free_list(struct list *my_list)
{
if(my_list == NULL)
return;
struct list *tmp;
while(my_list)
{
tmp = my_list;
my_list = my_list->next;
free(tmp);
}
}

C program crashes randomly when displaying my linked list

my code is supposed to find all the prime numbers between 1879 and 9987. everything seems to be working as intended except for when i go to display the linked list. it will display the first 6 elements roughly (it is random how far it will display each time the program is run). as you can see by running the code that it is printing all of the prime numbers required, it just doesn't store them all. any help is appreciated. I am using Dev C for my compiler.
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *link;
}n;
n *head = NULL;
void insert(int);
void display();
void erase();
void enqueue(int);
void pop();
void po$p();
void search(int);
void isprime();
int main(void)
{
int num,count, choice;
isprime();
while(1)
{
printf("\n 1. To display>");
printf("\n 2. To Delete the list>");
printf("\n 3. To insert at the end>");
printf("\n 4. Pop out of the stack>");
printf("\n 5. To delete at the back of the list>");
printf("\n 6. To search a particular node>");
printf("\n 7. To exit>");
printf("\n Enter your choice>");
scanf("%d",&choice);
switch(choice)
{
case 1:
display();
break;
case 2:
erase();
break;
case 3:
printf("Enter the data you want to insert at the end>");
scanf("%d",&num);
enqueue(num);
break;
case 4:
pop();
break;
case 5:
po$p();
break;
case 6:
printf("Enter the node you want to search>");
scanf("%d",&num);
search(num);
break;
case 7:
exit(0);
}
}
return 0;
}
void insert(int X)
{
n *temp;
temp = (n*)malloc(sizeof(n*));
temp->data = X;
temp->link = NULL;
if(head == NULL)
head = temp;
else
{
temp->link = head;
head = temp;
}
}
void display()
{
n *temp;
temp = (n*)malloc(sizeof(n*));
if(head == NULL)
printf("\n There is no list");
else
{
temp = head;
printf("\n head->");
while(temp != NULL)
{
printf("%d->",temp->data);
temp = temp->link;
}
printf("NULL");
}
}
void erase()
{
head = NULL;
}
void enqueue(int X)
{
n *temp,*newnode;
newnode = (n*)malloc(sizeof(n*));
newnode->data = X;
newnode->link = NULL;
temp = (n*)malloc(sizeof(n*));
if(head == NULL)
head = newnode;
else
{
temp = head;
while(temp->link != NULL)
temp = temp->link;
temp->link = newnode;
}
}
void pop()
{
n *temp;
temp = (n*)malloc(sizeof(n*));
if(head == NULL)
{
printf("\n nothing to pop");
}
else
{
temp = head;
printf("\n element popped is %d",temp->data);
head = head->link;
free(temp);
}
}
void po$p()
{
n *temp;
temp = (n*)malloc(sizeof(n*));
if(head == NULL)
{
printf("\n nothing to po$p");
}
else
{
temp = head;
while(temp->link->link != NULL)
temp = temp->link;
printf("\n Element po$ped is %d",temp->link->data);
temp->link = NULL;
}
}
void search(int X)
{
n *temp;
temp = (n*)malloc(sizeof(n*));
if(head == NULL)
{
printf("\n nothing to search");
}
else
{
temp = head;
while(temp->data != X && temp->link != NULL)
temp = temp->link;
if(temp->data == X)
printf("\n item in the list");
else if(temp->link == NULL)
printf("\n item is not in the list");
}
}
void isprime(){
int count,i,x;
for(x = 1879;x<=9987;x++){
count = 0;
for(i=2;i<=x/2;i++){
if(x%i==0){
count++;
break;
}
}
if(count==0 && x!= 1){
insert(x);
printf("%d",x);
}
}
}

Insertion at end in circular linked list not working in C

Please point out the error in the code.
The function insertatend() inserts for the first time but not again.
I'm trying to insert a node at the end of a circular linked list, but after inserting an element for the first time, it gets stuck in the while loop if we try to enter data again.
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
temp->next = head;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
while (p->next != head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
I think the mistake is here:
temp->next=head;
if(head==NULL){
head=temp;
}
When you enter your first element, head is null. So temp->next is set to NULL and head is set to temp.
When you enter your second element, it does this:
else{
while(p->next!=head)
p=p->next;
p->next=temp;}
Where p->next is null, so you will never have the situation that p->next == head and you will always be in the loop!
Edit:
So the solution aproach would be to change it to:
if(head==NULL){
head=temp;
}
temp->next=head;
Edit: second mistake in the display function: the loop doesn't print the last element. I just tested it and it is working fine.
So the complete code woud look like:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
temp->next = head;
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do
{
printf("%d ", p->data);
p = p->next;
} while (p != head);
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
Alternate version, using tail pointer instead of head pointer, for faster appends.
#include <stdlib.h>
#include <stdio.h>
struct node {
struct node *next;
int data;
};
typedef struct node node;
node *insertatend(node *tail, int value)
{
node *p;
p = malloc(sizeof(node));
p->data = value;
if(tail == NULL){
p->next = p;
} else {
p->next = tail->next;
tail->next = p;
}
return p;
}
void display(node *tail)
{
node *p = tail;
if (p == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do{
p = p->next;
printf("%d ", p->data);
}while(p != tail);
printf("\n");
}
int main()
{
node *tail = NULL;
int i;
for(i = 0; i < 8; i++)
tail = insertatend(tail, i);
display(tail);
return 0;
}

Resources