#Function to delete a NODE from a linked list

20 messages · Page 1 of 1 (latest)

urban perch
#
void delete(NODE* list, int index) {
    if (list==NULL) {
        printf("Invalid list\n");
        return;
    }
    if (index < 0 || index >= list_length(list)) {
        printf("Invalid index\n");
        return;
    }
    NODE* buffer=list;
    if (index==0) {
        NODE* temp=list;
        list=buffer->next_node;
        free(temp);
        return;
    };
    for (int i=0; i<index-2; i++) {
        buffer=buffer->next_node;
    }
    NODE* temp=buffer->next_node;
    buffer->next_node=buffer->next_node->next_node;
    free(temp);
}

The case where index==0 throws a seg fault. Can anyone tell why ?

tranquil terraceBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

left lark
#

hows your NODE looks like?

as a side note - please remember that c has no pass by reference semantics. i.e. even when you pass a pointer to a function - your function gets a copy of it (another, different pointer)pointing to the same 'thing'.

changes to that copied ptr won't reflect in the original. changes to the underlying 'thing' said copy points to - will reflect in the original

urban perch
#
typedef struct NODE {
    int data;
    struct NODE* next_node;
}NODE;

Heres the the struct NODE.

As a side note, Im also trying to get this into a library which can store any datatype, like a string or even custom structs.

left lark
#

well my comment above applies. doing list=buffer->next_node; only changes the local ptr with the name list. it doesn't change whatever original ptr points at. said original ptr will then point to a freed ptr after free(temp);. thus accessing it is UB

urban perch
#

oh man ive had this error thrice on this project at different parts

#

atleast i know how to fix it now

#

thankss, But I still need some more help

urban perch
left lark
#

do you want each node to be able to store different types? i highly advise you not to. regardless - yes, void * can be used, you can then allocate some space the size of the desired element and memcpy said element into your buffer

#

alternatively you can use the preprocessor to emulate templates

urban perch
left lark
#

thats fair. i'll just make note that in this case you'd pay for (possibly) 2 allocations (unless you use a flexible array member which is then compilcates things a bit). regardless, consider:

struct node {
  struct node *next;
  void *element;
};

struct ll {
  struct node *first;
  size_t element_size;
};

struct ll list_create(size_t element_size);

enum ll_err list_push(struct ll *ll, void *element);

...

and so on. when pushing an element in, you'd allocate some node and some node::element with the size ll::element_size. after which you can simply memcpy(node->element, element, ll->element_size) (checks omitted here)

#

this ofc might generate UB should the user pass in an element whos size is smaller than ll:element_size, though i'd argue thats on the user - not you

urban perch
#

im not getting it.

whats ll, does it function as the head_node, containing data about the size of whatever is to to be stored in the list ??

#

ill try implement something like this, maybe i can figure it out

left lark
#

ll is shorthand for linked list. by doing it that way you can:

  • store the info about the size of each element once
  • avoid the issue you originally had. you're no longer altering a copy of ll:first. you actually altering ll:first each and every time. this ofc isn't the only way one can avoid it. you can also pass a node ** or returns a node * (the new list)
tranquil terraceBOT
#

@urban perch Has your question been resolved? If so, type !solved :)

urban perch
#

mhm okaay i got it. ill get working on it. Thanks 😄

#

!solved