How to delete nodes in a doubly linked list - c

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.

Related

How to make this list a circular list?

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");
}

Add element linked list

#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node ** head, int n);
void display_list(node * head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
printf("Insert size of list: ");
scanf("%d",&n);
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void create_list(node **head,int n){
node *new,*tmp;
int num,i;
*head = malloc(sizeof(node));
if(*head == NULL){
printf("Memory can not be allocated.");
}
else{
printf("Insert element 1: ");
scanf("%d",&num);
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for(i=2;i<=n;i++){
new = malloc(sizeof(node));
if(new == NULL){
printf("Memory can not be allocated.");
break;
}
else{
printf("Insert element %d: ",i);
scanf("%d",&num);
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
scanf("%d", &num);
new->data = num;
new->next = NULL;
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
}
}
I don't understand why after using the add_e() function, the display_list() function gives to me only the last two number of the list. The add_e() fucntion should be add an element at the end of the list. What am i doing wrong?
Edit: Added create_list() function so you can understand better but now it says to me to add more details so I'm writing something.
In main, n is unitialized, so you'll get random/bad results.
The add_e should not use *head in the while or even do a while. The printf says "insert at beginning", which is different/simpler. This is what I've currently coded up/fixed.
You'd want to use a loop, if you [really] wanted to insert/append to the end of the list. But, the loop would still be incorrect, because you don't want to advance head when finding the end.
I've also fixed the printf for prompts and scanf
Here's a refactored/fixed version of your code with the bugs annotated:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
// NOTE/BUG: n is unitialized
#if 1
n = 5;
#endif
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void
create_list(node **head, int n)
{
node *new,
*tmp;
int num,
i;
*head = malloc(sizeof(node));
if (*head == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element 1: ");
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for (i = 2; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
else {
printf("Insert element %d: ", i);
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
fflush(stdout);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
#if 0
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
#else
if (*head == NULL)
*head = new;
else {
new->next = *head;
*head = new;
}
#endif
}
}
UPDATE:
In add_e, because I couldn't be sure if you wanted to insert at beginning of list [based on the printf] or at the end [based on the code], I created a version that is cleaned up a bit more and demonstrates both types:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_begin(node **head);
void add_end(node **head);
int
main(void)
{
int n;
node *head;
setbuf(stdout,NULL);
head = NULL;
printf("Enter initial number of list elements: ");
scanf(" %d",&n);
create_list(&head, n);
display_list(head);
add_begin(&head);
display_list(head);
add_end(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
node *cur;
if (head == NULL) {
printf("Empty list.\n");
}
for (cur = head; cur != NULL; cur = cur->next)
printf("DATA: %d\n", cur->data);
}
void
create_list(node **head, int n)
{
node *new, *tmp;
int num, i;
tmp = *head;
for (i = 1; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
printf("Insert element %d: ", i);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
if (*head == NULL)
*head = new;
else
tmp->next = new;
tmp = new;
}
}
// add_begin -- insert at before head of list
void
add_begin(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Insert element at the beginning: ");
scanf(" %d", &num);
new->data = num;
new->next = *head;
*head = new;
}
// add_end -- add to tail/end of list
void
add_end(node **head)
{
node *new;
node *tmp;
node *tail;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Append element at the end: ");
scanf(" %d", &num);
new->data = num;
new->next = NULL;
// find the tail
tail = NULL;
for (tmp = *head; tmp != NULL; tmp = tmp->next)
tail = tmp;
if (tail != NULL)
tail->next = new;
else
*head = new;
}

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);
}
}

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;
}

LinkedList with Char (String Issue

So I'm having issue with my code with the structure I'm using. I would like my structure to be able add,retrieve or sort but I'm getting a lot of problem with the structure. It work if I use only number but I need to user 3 string. One for firstname, lastname and phonenumber but I can't figure.
This is the code I'm having right now:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
char first[15];
char last[15];
char phone[12];
struct node *next;
}*head;
void append(int num, char f[15], char l[15],char p[12])
{
struct node *temp, *right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
right = (struct node *)head;
while (right->next != NULL)
right = right->next;
right->next = temp;
right = temp;
right->next = NULL;
}
void add(int num, char f[15], char l[15],char p[12])
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void addafter(int num, char f[15], char l[15],char p[12],int loc)
{
int i;
struct node *temp, *left, *right;
right = head;
for (i = 1; i<loc; i++)
{
left = right;
right = right->next;
}
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
left->next = temp;
left = temp;
left->next = right;
return;
}
void insert(int num, char f[15], char l[15],char p[12])
{
int c = 0;
struct node *temp;
temp = head;
if (temp == NULL)
{
add(num,f,l,p);
}
else
{
while (temp != NULL)
{
if (temp->data<num)
c++;
temp = temp->next;
}
if (c == 0)
add(num,f,l,p);
else if (c<count())
addafter(num,f,l,p, ++c);
else
append(num,f,l,p);
}
}
int delete(int num)
{
struct node *temp, *prev;
temp = head;
while (temp != NULL)
{
if (temp->data == num)
{
if (temp == head)
{
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("%d ", r->data);
r = r->next;
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while (n != NULL)
{
n = n->next;
c++;
}
return c;
}
int main()
{
int i, num;
char fname[15], lname[15], phone[12];
struct node *n;
head = NULL;
while (1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Retrieve\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 id, first, last and phone (Separte with space) : ");
scanf("%d %s %s %s", &num,fname,lname,phone);
insert(num,fname,lname,phone);
break;
case 2:
if (head == NULL){
printf("List is Empty\n");
}else{
printf("Element(s) in the list are : ");
}
display(n);
break;
case 3:
//To be made
//scanf("Retrieve this : %d\n", count());
break;
case 4:
if (head == NULL){
printf("List is Empty\n");
}else{
printf("Enter the number to delete : ");
scanf("%d", &num);
if (delete(num))
printf("%d deleted successfully\n", num);
else
printf("%d not found in the list\n", num);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
Thanks for anyone that could explain me the issue and or fix it.
Everywhere you have:
temp->data = num;
add the lines
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);

Resources