Deleting Nodes in a Linked List - c

After a lot of effort, I've managed to piece together a function that deletes some node from my linked list. But, out of sheer interest, I would like to find out how you can go about deleting the first node from the list, i.e. the head.
My program asks for a letter to delete, so for example.
Hello is stored in the list, the user inputs H for deletion, so that now the list is ello
At the moment with my code, the program crashes obviously as if H is deleted, there is no head, and the program doesn't know where to go to look for the list.
Below is my current implementation, any clues or hints on how to modify this code( I would like to keep it similar to how I have) to allow Head Node Deletion would be much appreciated!.
EDIT: In response to below
FullList DeleteNode(FullList temp, char c) {
FullList remember;
FullList ptr;
while (temp.head->c != c) {
remember.head = temp.head;
temp.head = temp.head->next;
}
ptr.head = temp.head->next;
free(temp.head);
remember.head->next = ptr.head;
return temp;
}
int main(void) {
FullList List;
char c, s;
List.head = NULL;
while ((c=getchar()) != '.') {
List = addToEnd(List, c);
}
scanf(" %c", &s);
List = DeleteNode(List, s);
while (List.head != NULL) {
printf("%c", List.head->c);
List.head = List.head->next;
}
return 0;
}
typedef struct List {
char c;
struct List *next;
}List;
typedef struct {
List *head;
List *tail;
}FullList;
List *insertList(char c, List *t1) {
List *t = (List*)calloc(1, sizeof(List));
t->c = c ;
t->next = t1;
return t;
}
FullList addToEnd(FullList c, char element) {
if (c.head == NULL) {
c.head = c.tail = insertList(element, NULL);
}else {
c.tail->next = insertList(element, NULL);
c.tail = c.tail->next;
}
return c;
}
void DeleteNode(FullList temp, char c) {
FullList remember;
FullList ptr;
while (temp.head->c != c) {
remember.head = temp.head;
temp.head = temp.head->next;
}
ptr.head = temp.head->next;
free(temp.head);
remember.head->next = ptr.head;
}
int main(void) {
FullList List;
char c, s;
List.head = NULL;
while ((c=getchar()) != '.') {
List = addToEnd(List, c);
}
scanf(" %c", &s);
DeleteNode(List, s);
while (List.head != NULL) {
printf("%c", List.head->c);
List.head = List.head->next;
}
return 0;
}

You can't do it without changing your existing code.
You're passing your FullList struct to your DeleteNode() function. This means that any changes to that struct are not visible back in main - the function is getting a copy of it.
You would need to change DeleteNode() to accept a pointer:
void DeleteNode(FullList *temp, char c)
Then when calling it main() you would do:
DeleteNode(&List, s);
By doing this, you can change the value of temp->head in your function and it will be visible back in main()
temp->head = temp->head->next;
Edit: The logic you'll need is:
Check to see if temp->head->c == c
If yes, replace temp->head with temp->head->next
else assign temp->head to a temp pointer *previous. Assign temp->head->next to a pointer *current. Loop through the list, moving both pointers. When you find a match in current->c, assign current->next to previous->next and free() the current node.

The way it is now, inside DeleteNode, when you change the argument, it only changes the local variable, not the one outside the function.
You either have to pass the FullList to DeleteNode by pointer so that modifications done to it will be visible to the caller, or modify a local one and return it, and the caller must assign the returned FullList to its list.
Either way, the changes made by DeleteNode must become visible to the caller.

Related

Swapping nodes in a linked list in C gets me to duplicate nodes

First of all I'd like to say that I'm quite new to pointers and linked lists so this is quite obscure to me still.
My goal in this program is to use strcmp as a tool to compare my data and therefore swap datas if necessary.
Here's my code :
#include "ft_list.h"
#include <stdlib.h>
#include <stdio.h>
void ft_print_list_data(t_list *list)
{
while (list)
{
printf("%p\n", list->data);
list = list->next;
}
}
t_list *ft_create_elem(void *data)
{
t_list *list;
list = NULL;
list = malloc(sizeof(t_list));
if (list)
{
list->data = data;
list->next = NULL;
}
return (list);
}
void ft_list_sort(t_list **begin_list, int (*cmp)())
{
t_list *list_ptr;
t_list *next_node;
t_list *temp;
list_ptr = *begin_list;
if (list_ptr)
{
while (list_ptr->next)
{
next_node = list_ptr->next;
while (next_node->next)
{
if ((*cmp)(list_ptr->data, next_node->data) > 0)
{
printf("if\n");
temp = next_node->next->data;
list_ptr->data = next_node->data;
next_node->data = temp;
}
next_node = next_node->next;
}
list_ptr = list_ptr->next;
}
}
}
int ft_strcmp(char *s1, const char *s2)
{
int x;
x = 0;
while (s1[x] == s2[x] && s1[x] != '\0' && s2[x] != '\0')
x++;
return (s1[x] - s2[x]);
}
int main(void)
{
char str1[] = "a";
char str2[] = "d";
char str3[] = "c";
char str4[] = "b";
char str5[] = "g";
char str6[] = "f";
char str7[] = "e";
t_list *begin_list;
begin_list = ft_create_elem(&str1);
begin_list->next = ft_create_elem(&str2);
begin_list->next->next = ft_create_elem(&str3);
begin_list->next->next->next = ft_create_elem(&str4);
begin_list->next->next->next->next = ft_create_elem(&str5);
begin_list->next->next->next->next->next = ft_create_elem(&str6);
begin_list->next->next->next->next->next->next = ft_create_elem(&str7);
printf("list\n");
ft_print_list_data(begin_list);
ft_list_sort(&begin_list, &ft_strcmp);
printf("updated\n");
ft_print_list_data(begin_list);
return (0);
}
Here's what I'm getting in the terminal :
list
0x7ffcfc6615ea
0x7ffcfc6615ec
0x7ffcfc6615ee
0x7ffcfc6615f0
0x7ffcfc6615f2
0x7ffcfc6615f4
0x7ffcfc6615f6
if
if
if
if
updated
0x7ffcfc6615ea
0x7ffcfc6615f0
0x7ffcfc6615f0
0x7ffcfc6615f4
0x7ffcfc6615f6
0x7ffcfc6615f6
0x7ffcfc6615f6
As you can see I get duplicates instead of swaps. I have no clue why, I guess I'm not understanding well how pointers work so I'm, as it seems, overwritting in some way.
I would really appreciate if a gentle soul could show me the light on what I'm misunderstanding !
Thank you for you help.
In ft_list_sort, the nodes whose data member values are being compared are not the same as the nodes whose data member values are being swapped:
if ((*cmp)(list_ptr->data, next_node->data) > 0)
{
printf("if\n");
temp = next_node->next->data;
list_ptr->data = next_node->data;
next_node->data = temp;
}
Specifically, the first line of the swap code temp = next_node->next->data; is completely unrelated to the node data member values being compared. Changing that line to temp = list_ptr->data; fixes that problem:
if ((*cmp)(list_ptr->data, next_node->data) > 0)
{
printf("if\n");
temp = list_ptr->data;
list_ptr->data = next_node->data;
next_node->data = temp;
}
Another problem is that while (next_node->next) does not consider the final node of the list for swapping. Changing it to while (next_node) fixes that problem.
Another problem is that the temp variable has the wrong type. It should be the same type as the data member of t_list, but if that is a pointer type, temp can be type void *.
Another problem is that the cmp function pointer has no prototype. It should probably be something like int (*cmp)(const void *, const void *), but the prototype of the function it points to would need the same prototype.
By changing if (list_ptr) to while (list_ptr) a level of indentation can be removed.
Putting all that together:
void ft_list_sort(t_list **begin_list, int (*cmp)(const void *, const void *))
{
t_list *list_ptr;
t_list *next_node;
void *temp;
list_ptr = *begin_list;
while (list_ptr)
{
next_node = list_ptr->next;
while (next_node)
{
if ((*cmp)(list_ptr->data, next_node->data) > 0)
{
printf("if\n");
temp = list_ptr->data;
list_ptr->data = next_node->data;
next_node->data = temp;
}
next_node = next_node->next;
}
list_ptr = list_ptr->next;
}
}
For the comparison function, assuming you want to leave ft_strcmp as is, you will need a wrapper function with the correct prototype:
int my_datacmp(const void *a, const void *b)
{
return ft_strcmp(a, b);
}
(Note: in ft_strcmp, both parameters should be type const char *. The current version is missing the const for one of the parameters.)
Then pass my_datacmp in the call to ft_list_sort:
ft_list_sort(&begin_list, &my_datacmp);
(Note: You can use my_datacmp instead of &my_datacmp because both expressions are pointers to the my_datacmp function.)
this is a little tricky and I might not be able to explain it well, but Im gonna try anyway.
In this swap
temp = next_node->next->data;
list_ptr->data = next_node->data;
next_node->data = temp;
you are merely swapping the pointers, and not the actual data...
Lets say, the if statement if ((*cmp)(list_ptr->data, next_node->data) > 0) is true, then
temp = next_node->next->data; // temp is assigned pointer to the next->data
list_ptr->data = next_node->data;
next_node->data = temp;
After this, next_node->data is pointing to the next_node->next->data, but so is the list_ptr-data, because it was assigned so in previous command. If you are trying to copy the actual data, not just asign one pointer to another, then maybe using strcpy() is the right way to go.
So after all is done, you have two pointers, which are pointing to the same space (from which the duplicates probably come from), and you have lost the pointer to the list_ptr->data, because you reassigned it point to next_node->data
This is probably very confusing, so to sum it up, if you want to change the actual data and not just reassign the pointers, I suggest using
temp = list_ptr->data;
strcpy(list_ptr->data, next_node->data);
strcpy(next_node->data, temp);
Also I think you probably meant to use temp = next_node->next->data instead of temp = next_node->next->data ,as I dont see the reason you want to take the data of the next item, when you used your comparing if statement on temp = next_node->data
Normal Suggestion, I don't know what is the code for t_list , but i think temp should be of the same datatype of the 'data' member of your t_list structure.

print from users input linked list of struct

I am required to have a list of structs of sentence nodes that point to a struct of word nodes. I am trying to print the user's input.
I have a program that runs properly when I manually give it the input (see test section of the code). It does not, however, work when I use my input1() function.
I've tried debugging it, but I can't seem to find the problem.
I removed all printf lines that I used to debug. I also removed all the irrelevant code.
I am looking to know how to fix it and what is wrong so I can run it with no problems.
What I learned from debugging it is that (only when using input1() and not in the test) the head is overwritten every time and all the nodes as well.
I also tried using a double pointer instead of returning para but that didn't help.
any help will be appreciated,
thanks in advance
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct word
{
char * ch;//poiter to char
}
W;
typedef struct sentence
{
W * currentWord;//pointer to a word
int lineNumber;// holds the line number
int numbersOfWords;//holds the number of words
struct sentence* link;
}
sent;
typedef struct list
{
sent* head;
int count;
}
LISTS;
LISTS* createList()
{
LISTS* list;
list= (LISTS*) malloc (sizeof (LISTS));
if (list)
{
list-> head = NULL;
list-> count = 0;
}
return list;
} // createList
void printList(LISTS* list)
{
sent *temp = list -> head;
//iterate the entire linked list and print the data
while(temp != NULL)
{
printf("%s\n", temp->currentWord->ch);
temp = temp->link;
}
// printf("NULL\n");
}
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = (sent * ) malloc(sizeof(sent)))){
printf(" Memory can not be allocated.");
return;
}
newPtr->currentWord = itemPtr;
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current -> link = newPtr;
}
(list->count)++;
return;
} // insertList
LISTS * input1(LISTS *para)
{
char * line;
line = (char * ) malloc(1000 * sizeof(char));
line[0] = '\0';
while (line[0] != '\n')
{
W word;
word.ch = (char * ) malloc(100);
printf(" Please input a line : ");
fgets(line, 1000, stdin);
if(line[0] != '\n'){
strcpy(word.ch, line);
insertSentList(para,&word);
}
}
free(line);
return para;
}
int main()
{
///////////////////test////////////////
LISTS* list = createList();
W word;
word.ch= "word0 ";
W word1;
word1.ch= "word1 ";
W word2;
word2.ch= "word2";
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
printList(list);
///////////////////test////////////////
LISTS *para = createList();
para= input1(para);
printList(para);
return 0;
}
Main problem with the posted code is that "ownership" of the sent and W objects in a list is not well defined. For example word.ch= "word0 "; in main sets the ch pointer pointing to a string literal (which it does not own), but word.ch = malloc(100); in input1 points it to dynamically allocated memory (which it should own, and remember to free later). Because of this, memory allocations cannot be tracked reliably and, even in the cases where things appear to "work", there are multiple memory leaks. It also breaks when the inserted objects are local variables that do not live for the entire lifetime of the list object.
The simplest (if not necessarily the best or most efficient) solution would be to dynamically allocate all objects that go into the list, make the list own them all, and add a function to cleanup once done. To that end insertSentList could be modified as follows.
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = malloc(sizeof(sent)))){
printf(" Memory can not be allocated.\n");
return;
}
W *newItem = malloc(sizeof(W)); // <-- make a deep copy of the `itemPtr` argument
newItem->ch = strdup(itemPtr->ch); // including a copy of the string itself
newPtr->currentWord = newItem; // <-- save the copy in the list, not the argument
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current->link = newPtr;
}
list->count++;
} // insertList
For proper cleanup and to avoid memory leaks, the following freeList should be called for each list pointer returned by createList and filled by insertSentList.
void freeList(LISTS *list)
{
sent *temp = list->head;
while(temp != NULL)
{
sent *next = temp->link;
free(temp->currentWord->ch);
free(temp->currentWord);
free(temp);
temp = next;
}
free(list);
}

Function to insert node in linked list

I'm reading in words from a dictionary and then adding them to linked lists in a hash table. This works fine when I try inserting the nodes for each word within the while loop.
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
return false;
}
// Set all next pointers to NULL in hash table
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
node *pNode = getNode(word);
if (table[key] != NULL)
{
pNode->next = table[key];
}
table[key] = pNode;
words++;
}
fclose(dict);
return true;
}
I've tried refactoring this to a function insertNode with the exact same code but it doesn't work and the nodes seem to get lost and cause a memory leak. I assume it has something to do with how the arguments are passed into the function but as head is a pointer I would've thought it would work fine.
void insertNode(node *head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = head;
}
// Now point head to new node
head = pNode;
}
so the while loop within load would just call the function (which is defined before)
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
// Add value to Hash table with head of linked list
insertNode(table[key], word);
words++;
}
As the 'head' variable is a pointer, you can just pass the value of 'head' by this pointer not the pointer itself, and in this case you try to override the local pointer inside the function.
Well look at this example to assign/change value to the pointer:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by copy
void initialize(A* obj) {
obj = new A(); // obj not null here
obj->x = 2;
printf("x: %d\n", obj->x);
}
int main() {
A *a = nullptr;
initialize(a);
// a is still null here (pointer passed by copy)
printf("x: %d\n", a->x); // seg fault here, read on null
return 0;
}
The following code as you can see is incorrect. To fix this example you have to change the function prototype, and pass the pointer by pointer so it should lool like this:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by pointer
void initialize(A** obj) {
*obj = new A(); // obj not null here
(*obj)->x = 2;
printf("x: %d\n", (*obj)->x);
}
int main() {
A *a = nullptr;
initialize(&a); // get the pointer address
// a is valid object here
printf("x: %d\n", a->x); // no error, x == 2
return 0;
}
So in your case it should be:
insertNode(&table[key], word);
and
void insertNode(node **head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (*head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = *head;
}
// Now point head to new node
*head = pNode;
}

Deleting a linked list node in a C function doesn't transfer to the calling function

I have this C function which is supposed to find an element in the linked list which has a specific "pos" value, delete it, and return the deleted value to the calling function. It does delete the item, but the change isn't saved in the calling function, the list just doesn't get updated with the new changes.
My list is structured like this:
struct list{
int value;
int pos;
struct list * next_ptr;
};
And my C function is this:
bool findDeleteElement(struct list **ptr, int position, int *value){
struct list** temp = ptr;
if(*ptr!=NULL){
while((*ptr)->pos!=position) ptr=&(*ptr)->next_ptr; //Gets to desired node
temp=ptr;
value=&(*ptr)->value; //saves the value
temp=&(*temp)->next_ptr; //Goes to next node
ptr=temp; //Makes ptr point to next node
return 1;
}
else return 0;
}
I just can't see what I'm missing.
I'm a beginner so I probably made a simple mistake.
Change to:
*value = (*ptr)->value; //saves the value
You only set value, the local copy of your external variable's address. This does not change your external variable in the calling function.
Some question:
What happens when position has the wrong value, such that no node is found?
What's the purpose of temp = ptr;, because temp is overwritten by temp = &(*temp)->next_ptr; without having been used.
Disclaimer: I've not further checked this function.
I kindly advise you to take on other code formatting rules that add more air and make things more readable. Here's an example:
bool findDeleteElement(struct list **ptr, int position, int *value)
{
struct list** temp = ptr;
if (*ptr != NULL)
{
// Gets to desired node
while((*ptr)->pos != position)
{
ptr = &(*ptr)->next_ptr;
}
temp = ptr;
*value = (*ptr)->value; // Saves the value
temp = &(*temp)->next_ptr; // Goes to next node
ptr = temp; // Makes ptr point to next node
return 1;
}
else
{
return 0;
}
}
You are confused about pointers and dereferencing and what & and * actually do. This is a normal state of affairs for a beginner.
To start with, ptr and value when used without * preceding them are function arguments and like automatic (local) variables they disappear when the function scope exits. So this statement:
value=&(*ptr)->value;
Merely changes the value of value i.e. what it points to and has no visible effect to the caller. What you need to change is the thing that value points to. i.e. the statement should look like this:
*value = (*ptr)->value;
The difference is that instead of setting value to the address of (*ptr)->value it sets what valuepoints to to (*ptr)->value.
You have a similar problem with ptr. But your problems are more subtle there because you are also trying to use it as a loop variable. It's better to separate the two uses. I'd write the function something like this:
bool findDeleteElement(struct list **head, int position, int *value)
{
struct list* temp = *head;
struct list* prev = NULL;
while(temp != NULL && temp->pos != position)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) // position not found
{
return false;
}
else
{
*value = temp->value;
// Now need to delete the node.
if (prev != NULL)
{
// If prev has been set, we are not at the head
prev->next = temp->next; // Unlink the node from the list
}
else // We found the node at the head of the list
{
*head = temp->next;
}
free(temp); // Assumes the node was malloced.
return true;
}
}
The above is not tested or even compiled. I leave that as an exercise for you.
int delete(struct llist **pp, int pos, int *result)
{
struct llist *tmp;
while ( (tmp = *pp)) {
if (tmp->pos != pos) { pp = &tmp->next; continue; }
*result = val;
*pp = tmp->next;
free(tmp);
return 1;
}
return 0;
}

Pointers to pointers - linked list mess

I'm writing a simple C program to manage a linked list defined as follow:
typedef struct node {
int value;
struct node *next;
} *List;
I reviewed the code and it seems okay but when printing results something is not working well.
My main, with problems on comments:
int main(void) {
List n = list_create(1);
insert(n, 2);
insert(n, 3);
insert(n, 5);
insert(n, 4);
//something here does not work properly. It produces the following output:
//Value: 1
//Value: 2
//Value: 3
//Value: 4
//where is value 5?
print_list(n);
delete(n, 3);
print_list(n);
return 0;
}
I don't know where am I destroying list structure. These are my functions, to debug, if you are too kind.
List list_create(int value) {
List new = malloc(sizeof(struct node));
new->value = value;
new->next = NULL;
return new;
}
List new_node(int value, List next_node) {
List new = malloc(sizeof(struct node));
new->value = value;
new->next = next_node;
return new;
}
void print_list(List l) {
List *aux;
for (aux = &l; (*aux) != NULL; aux = &((*aux)->next))
printf("Valor: %d\n", (*aux)->value);
}
void insert(List l, int value) {
List *p;
for (p = &l; (*p) != NULL; p = &((*p)->next))
if ((*p)->value > value) {
List tmp = *p;
List new = new_node(value, tmp);
*p = new;
break;
}
*p = new_node(value, NULL);
}
void delete(List l, int value) {
List *p;
for (p = &l; (*p) != NULL; p = &((*p)->next))
if ((*p)->value == value) {
List del = (*p);
(*p) = ((*p)->next);
free(del);
break;
}
}
This code has (at least) two bugs:
The line
if ((*p)->value > value){
means that if you start the list with 1 as the first value and then try to insert 2,3,4..., the body of the 'if' statement never runs, so nothing ever gets inserted.
If you insert a value below the starting value, you have to modify the list pointer itself. However, as #EOF alluded, you are trying to modify a value passed to a function by taking its address. This won't work. &l does not give you the address of the List you passed, it gives you the address of the local copy on insert()'s stack. You are better off modifying the values of first element of the list 'in place'. If you really want to make the List parameter mutable, you'll need to pass it as a List *, and call the function with the address of the list (e.g. insert(&n,2); ) Your delete() function suffers from the same problem - try deleting the first element of the list.
Try this for your insert function:
void insert(List l, int value)
{
List p;
// Find end of list or highest item less than value
for(p = l; p->next != NULL && p->next->value < value; p = p->next);
if (p->value >= value) {
// Over-write p with new value, and insert p as a new one after.
// This saves having to modify l itself.
int tmpval = p->value;
p->value = value;
p->next = new_node(tmpval, p->next);
} else {
// Insert new item after p
p->next = new_node(value, p->next);
}
}
A comment: it is possible the way you are using pointers is not helping the debugging process.
For example, your print_list() could be re-written like this:
void print_list(List l){
List aux;
for(aux = l; aux != NULL; aux = aux->next)
printf("Valor: %d\n", aux->value);
}
and still behave the same. It is generally good practice not to 'hide' the pointer-like nature of a pointer by including a '*' in the typedef.
For example, if you define your list like this:
typedef struct node{
int value;
struct node *next;
} List
And pass it to functions like this:
my_func(List *l, ...)
then it'll make some of these issues more apparent. Hope this helps.
There are many problems in your code:
Hiding pointers behind typedefs is a bad idea, it leads to confusion for both the programmer and the reader.
You must decide whether the initial node is a dummy node or if the empty list is simply a NULL pointer. The latter is much simpler to handle but you must pass the address of the head node to insert and delete so they can change the head node.
printlist does not need an indirect pointer, especially starting from the address of the pointer passed as an argument. Simplify by using the Node pointer directly.
in insert you correctly insert the new node before the next higher node but you should then return from the function. Instead, you break out of the switch and the code for appending is executed, replacing the inserted node with a new node with the same value and a NULL next pointer. This is the reason 5 gets removed and lost when you insert 4. Furthermore, you should pass the address of the head node so a node can be inserted before the first.
delete starts from the address of the argument. It cannot delete the head node because the pointer in the caller space does not get updated. You should pass the address of the head node.
You should avoid using C++ keywords such as new and delete in C code: while not illegal, it confuses readers used to C++, confuses the syntax highlighter and prevents compilation by C++ compilers.
Here is a simplified and corrected version:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
Node *new_node(int value, Node *next_node) {
Node *node = malloc(sizeof(*node));
if (node != NULL) {
node->value = value;
node->next = next_node;
}
return node;
}
void print_list(Node *list) {
for (; list != NULL; list = list->next)
printf("Valor: %d\n", list->value);
}
void insert_node(Node **p, int value) {
while ((*p) != NULL && (*p)->value < value)
p = &(*p)->next;
*p = new_node(value, *p);
}
void delete_node(Node **p, int value) {
while (*p != NULL) {
if ((*p)->value == value) {
Node *found = *p;
*p = (*p)->next;
free(found);
// return unless delete() is supposed to remove all occurrences
return;
} else {
p = &(*p)->next;
}
}
}
int main(void) {
Node *n = NULL;
insert_node(&n, 2);
insert_node(&n, 3);
insert_node(&n, 5);
insert_node(&n, 4);
insert_node(&n, 1);
print_list(n);
delete_node(&n, 3);
print_list(n);
delete_node(&n, 1);
print_list(n);
return 0;
}

Resources