Reputation: 1257
I have a linked list where each node stores a word and a number. I can add nodes at the top of the list (push
), at the center of the list (insertAfter
) and at the end of the list (append
). I now added a function to delete nodes, where it will take a char, it will search that char through the list and delete the node that stores that char.
The problem is that deleteNode
will work with a normal node added at the top of the list, but when i append a node at the end or add it at the middle of the list it won't work.
Tl;dr deleteNode
works with nodes created with push
but not with nodes created with append
or insertAfter
.
The error i get is segmentation fault
, so i don't have a specific error from the compiler. I'm trying to debug it by running different parts of the code but i still can't find the problem.
struct Node
{
int data;
char *word;
struct Node *next;
};
void push(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
/* Given a node prev_node, insert a new node after the given
prev_node */
void insertAfter(struct Node* prev_node, int new_data, char *new_word)
{
if (prev_node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct Node* new_node =(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = prev_node->next;
prev_node->next = new_node;
}
void append(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
struct Node *last = *head_ref;
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
return;
}
void deleteNode(struct Node **head_ref, char *word)
{
struct Node* temp = *head_ref, *prev;
if (strcmp(word, (*head_ref)->word)==0)
{
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp); // Free memory
}
Upvotes: 1
Views: 68
Reputation: 59184
The answers you have are OK, but just for the record, after enough practice it should look kinda like this:
void deleteNode(struct Node **pplist, char *word)
{
for (struct Node *n = *pplist; n; n=*(pplist = &(n->next)))
{
if (!strcmp(n->word,word))
{
*ppnode = n->next;
free(n->word);
free(n);
break;
}
}
}
The point is that you can just move the pointer to the node pointer through the list instead of treating the head as a special case.
Similarly, you can do append like this:
void append(struct Node** pplist, int new_data, char *new_word)
{
for(; *pplist; pplist=&((*pplist)->next));
push(pplist, new_data, new_word);
}
and insert_after(prev...
is just push(&(prev->next)...
Upvotes: 1
Reputation: 318
Apart from what was stated by @4386427, you are not allocating enough space for your strings there:
new_node->word= malloc(strlen(new_word));
Notice that the C library function size_t strlen(const char *str)
computes the length of the string str up to, but not including the terminating null character. So i would rather suggest:
new_node->word= malloc(strlen(new_word) + 1);
new_node->word[strlen(new_word)] = '\0';
This can cause you some problems with the memory. ;)
Or event better, use calloc
, so the second line will be unnecessary:
new_node->word= calloc(strlen(new_word) + 1, sizeof(char));
Upvotes: 1
Reputation: 44274
This part looks strange:
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
In the strcmp
you use head_ref
but in the body you update temp
to move to the next element.
Did you intend to do:
while (strcmp(word, temp->word)!=0)
{
prev = temp;
temp = temp->next;
}
Further there should probably some check for temp
being NULL. Like:
while (temp && strcmp(word, temp->word)!=0)
Upvotes: 2