From 38496b78838a6faea8b6c68a8b5d455e5181234f Mon Sep 17 00:00:00 2001 From: Bruce Cowan <bruce@bcowan.me.uk> Date: Mon, 23 Dec 2019 13:34:37 +0000 Subject: [PATCH] More featureful linked list --- lib/types/array.h | 6 ++-- lib/types/slist.c | 89 +++++++++++++++++++++++++++++++++++++++++++---- lib/types/slist.h | 21 ++++++++--- lib/types/types.h | 8 +++++ src/list-test.c | 42 ++++++++++++---------- 5 files changed, 133 insertions(+), 33 deletions(-) create mode 100644 lib/types/types.h diff --git a/lib/types/array.h b/lib/types/array.h index 44f0a7b..25c432a 100644 --- a/lib/types/array.h +++ b/lib/types/array.h @@ -22,11 +22,9 @@ #include <stdbool.h> #include <stddef.h> -typedef struct _Array Array; +#include "types.h" -typedef void (*FreeFunc) (void *element); -typedef double (*ValueFunc) (const void *element); -typedef int (*CompareFunc) (const void *a, const void *b); +typedef struct _Array Array; // Fundamental functions Array * array_new (FreeFunc func); diff --git a/lib/types/slist.c b/lib/types/slist.c index 2bcbef4..a15cc63 100644 --- a/lib/types/slist.c +++ b/lib/types/slist.c @@ -7,17 +7,94 @@ SList * slist_prepend (SList *list, void *data) { - SList *new = malloc (sizeof (SList)); - new->data = data; - new->next = list; + SList *new = malloc (sizeof (SList)); + new->data = data; + new->next = list; - return new; + return new; +} + +SList * +slist_find (SList *list, + const void *data) +{ + for (SList *l = list; l; l = l->next) + { + if (l->data == data) + return l; + } + + return NULL; +} + +SList * +slist_nth (SList *list, + int idx) +{ + int i = 0; + + for (SList *l = list; l; l = l->next) + { + if (i == idx) + return l; + i++; + } + + return NULL; +} + +void +slist_foreach (SList *list, + ForEachFunc func, + void *user_data) +{ + for (SList *l = list; l; l = l->next) + func (l->data, user_data); +} + +static inline void +slist_free_one (SList *list, + FreeFunc func) +{ + if (func) + func (list->data); + + free (list); +} + +SList * +slist_remove (SList *list, + void *data, + FreeFunc func) +{ + if (!list) + return NULL; + + // If the first element is the one we're looking for + if (list->data == data) + { + SList *head = list->next; + slist_free_one (list, func); + return head; + } + + SList *prev = list; + for (SList *l = list; l; prev = l, l = l->next) + { + if (l->data == data) + { + prev->next = l->next; + slist_free_one (l, func); + break; + } + } + + return list; } void slist_free_all (SList *list, FreeFunc func) { - for (SList *l = list; l; l = l->next) - func (l); + slist_foreach (list, (ForEachFunc) slist_free_one, NULL); } diff --git a/lib/types/slist.h b/lib/types/slist.h index ae55f13..243a0b6 100644 --- a/lib/types/slist.h +++ b/lib/types/slist.h @@ -1,16 +1,27 @@ #pragma once -typedef void (*FreeFunc) (void *value); +#include "types.h" typedef struct _SList SList; struct _SList { - void *data; - SList *next; + void *data; + SList *next; }; -SList * slist_prepend (SList *list, - void *data); +SList * slist_prepend (SList *list, + void *data); +SList * slist_find (SList *slist, + const void *data); +SList * slist_nth (SList *slist, + int index); +void slist_foreach (SList *list, + ForEachFunc func, + void *user_data); + +SList * slist_remove (SList *list, + void *data, + FreeFunc func); void slist_free_all (SList *list, FreeFunc func); diff --git a/lib/types/types.h b/lib/types/types.h new file mode 100644 index 0000000..4db1954 --- /dev/null +++ b/lib/types/types.h @@ -0,0 +1,8 @@ +#pragma once + +typedef void (*FreeFunc) (void *data); +typedef void (*ForEachFunc) (void *data, + void *user_data); +typedef double (*ValueFunc) (const void *element); +typedef int (*CompareFunc) (const void *a, + const void *b); diff --git a/src/list-test.c b/src/list-test.c index 98aad53..31333b5 100644 --- a/src/list-test.c +++ b/src/list-test.c @@ -1,4 +1,4 @@ -#include "slist.h" +#include <slist.h> #include <stdio.h> #include <stdlib.h> @@ -7,38 +7,44 @@ static SList * add_data (SList *list) { - char buffer[128]; + char buffer[128]; - printf ("Input the data "); - scanf ("%s", buffer); + printf ("Input the data "); + scanf ("%s", buffer); - char *str = strdup (buffer); - return slist_prepend (list, str); + char *str = strdup (buffer); + return slist_prepend (list, str); } static void print_data (SList *list) { - SList *l; + SList *l; - for (l = list; l != NULL; l = l->next) - { - printf ("%s\n", (char *) l->data); - } + for (l = list; l; l = l->next) + printf ("%s\n", (char*) l->data); } int -main (void) +main(void) { - SList *list = NULL; + SList *list = NULL; + + for (int i = 0; i < 3; i++) + { + list = add_data (list); + print_data (list); + } - while (1) + for (int i = 2; i >= 1; i--) { - list = add_data (list); - print_data (list); + void *el = slist_nth (list, i)->data; + list = slist_remove (list, el, NULL); } + puts ("After deletion: "); + print_data (list); - slist_free_all (list, free); + slist_free_all(list, NULL); - return 0; + return 0; } -- GitLab