linked list - Error deleting node from first position in c -
as many previous posts show, making code simulate crazy 8's card game. have delete node function meant delete card deck being played. works cards after first, every time try delete first card (node) list not delete , messes whole program after it. here function:
void deletenode(card *head, int coordinate) { card *current = head; card *temp = null; temp = current; int count = 1; while (head != null) { if (coordinate == 0) { current = current->listp; free(temp); break; } else if (count == coordinate) { temp = current->listp; current->listp = current->listp->listp; free(temp); break; } else { count++; current = current->listp; } } }
the *head passed top of hand being played. coordinate number of card user wants play. example, if first card in deck q of hearts , that's want play, enter one. in function call, subtract 1 user choice match list (since list starts @ 0). appreciated. can't move on project until problem resolved!
as mentioned in comments, problem running due not passing address-of list deletenode
function. problem basic, catches lot of people. address of linked-list, address of first node. when deleting first node, must set new list address next node address in order list continue operate.
when pass pointer function, e.g. void deletenode(card *head, ...
, function deletenode
receives copy of pointer head
. copy has address own , address has no relation address of pointer in calling function. value of pointer same in deletenode
in caller, address different.
the problem occurs when delete first node in deletenode
. memory free
'd, , deletenode
function returns. in caller (presumably main()
), next time attempt access head
-- bam! segfault. why? address head
never updated in main
, still points original node -- , did memory original node in deletenode
? (you called free
on pointer pointed block of memory holding first node -- gone...)
to fix problem, pass address-of list (head
) deletenode
. (e.g. void deletenode(card **head, ...
). operating on address of head
(e.g. pointer-to-the-pointer-head). before deleting first node can set *head = head->listp;
, have new list address reflected in calling function (main()
). example, code written as:
void delnode (card **head, int coordinate) { card *current = *head; card *victim = null; victim = current; int count = 1; while (current != null) { if (coordinate == 0) { *head = current->listp; free (victim); break; } else if (count == coordinate) { victim = current->listp; current->listp = current->listp->listp; free (victim); break; } else { count++; current = current->listp; } } }
however, can make few improvements logic of function, minimal effort. e.g.
void delnode (card **head, int coordinate) { card *current = *head; card *victim = current; int count = 1; if (coordinate == 0) { *head = current->listp; free (victim); return; } while (current != null) { if (count == coordinate) { victim = current->listp; current->listp = current->listp->listp; free (victim); return; } count++; current = current->listp; } }
lastly, visit links describing how ask question , how create minimal, complete, , verifiable example. providing necessary details, including code, , associated errors, if any, allow here question.
this question perfect example. , compile , confirm problem or answer, asking folks here write sample program makes educated guess @ underlying list structure presumably is. when ask question here, purpose of providing mcve others may compile code , confirm problem having, , if need be, run compiled code through debugger in order you. more , more of positive response if follow minimal suggestions , rule of site there you.
that being said, can confirm operation of delete small bit of sample code.
#include <stdio.h> #include <stdlib.h> typedef struct card { int cardno; struct card *listp; } card; card *createnode (int c); card *insert (card **list, int c); void prnlist (card *list); void delnode (card **head, int coordinate); void dellist (card *list); void *xcalloc (size_t nmemb, size_t sz); int main (void) { card *list = null; insert (&list, 18); /* insert test nodes */ insert (&list, 6); insert (&list, 54); insert (&list, 12); insert (&list, 60); insert (&list, 30); printf ("\noriginal list:\n"); prnlist (list); printf ("\ndeleting node: 2\ndeleting node: 0\n"); delnode (&list, 2); /* delete 3rd & 1st nodes */ delnode (&list, 0); printf ("\nfinal list:\n"); prnlist (list); dellist (list); /* free allocated memory */ return 0; } card *createnode (int c) { card *node = xcalloc (1, sizeof *node); node->listp = null; node->cardno = c; return node; } card *insert (card **list, int c) { card *iter = *list; card *node = createnode (c); if (!*list) { /* add 1st node list */ *list = node; return *list; } /* insert other nodes @ end */ (; iter->listp; iter = iter->listp) {} iter->listp = node; return *list; } void prnlist (card *list) { card *iter = list; (; iter->listp; iter = iter->listp) printf (" cardno : %d\n", iter->cardno); printf (" cardno : %d\n", iter->cardno); } void delnode (card **head, int coordinate) { card *current = *head; card *victim = current; int count = 1; if (coordinate == 0) { *head = current->listp; free (victim); return; } while (current != null) { if (count == coordinate) { victim = current->listp; current->listp = current->listp->listp; free (victim); return; } count++; current = current->listp; } } void dellist (card *list) { card *iter = list; while (iter) { card *victim = iter; iter = iter->listp; free (victim); } } void *xcalloc (size_t nmemb, size_t sz) { void *memptr = calloc (nmemb, sz); if (!memptr) { fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n"); exit (exit_failure); } return memptr; }
example use/output
$ ./bin/lldelcard original list: cardno : 18 cardno : 6 cardno : 54 cardno : 12 cardno : 60 cardno : 30 deleting node: 2 deleting node: 0 final list: cardno : 6 cardno : 12 cardno : 60 cardno : 30
memory error check
in code write dynamically allocates memory, have 2 responsibilites regarding block of memory allocated: (1) preserves pointer starting address block of memory so, (2) can freed when no longer needed.
it imperative use memory error checking program insure haven't written beyond/outside allocated block of memory, attempted read or base jump on unintitialized value , confirm have freed memory have allocated.
for linux valgrind
normal choice. there many subtle ways misuse new block of memory. using memory error checker allows identify problems , validate proper use of of memory allocate rather finding out problem exists through segfault
. there similar memory checkers every platform. simple use, run program through it.
$ valgrind ./bin/lldelcard ==9094== memcheck, memory error detector ==9094== copyright (c) 2002-2013, , gnu gpl'd, julian seward et al. ==9094== using valgrind-3.10.1 , libvex; rerun -h copyright info ==9094== command: ./bin/lldelcard ==9094== original list: cardno : 18 cardno : 6 cardno : 54 cardno : 12 cardno : 60 cardno : 30 deleting node: 2 deleting node: 0 final list: cardno : 6 cardno : 12 cardno : 60 cardno : 30 ==9094== ==9094== heap summary: ==9094== in use @ exit: 0 bytes in 0 blocks ==9094== total heap usage: 6 allocs, 6 frees, 96 bytes allocated ==9094== ==9094== heap blocks freed -- no leaks possible ==9094== ==9094== counts of detected , suppressed errors, rerun with: -v ==9094== error summary: 0 errors 0 contexts (suppressed: 1 1)
always confirm all heap blocks freed -- no leaks possible , equally important error summary: 0 errors 0 contexts.
good luck coding.
Comments
Post a Comment