#include #include #include #include "assert.h" struct list_node { int data; struct list_node *next; }; typedef struct list_node list_node_t; struct list { list_node_t * head; }; typedef struct list list_t; void list_init (list_t * list) { list->head = NULL; } int list_length(list_t * list) { list_node_t *cur; int count = 0; cur = list->head; while (cur != NULL) { count++; cur = cur->next; } return count; } bool list_empty(list_t * list) { return (list->head == NULL); } void list_print(list_t * list) { list_node_t *cur; cur = list->head; while (cur != NULL) { printf("%d ", cur->data); cur = cur->next; } printf("\n"); } void list_add(list_t * list, list_node_t * item) { list_node_t *cur; assert(item->next == NULL); if (list_empty(list)) { list->head = item; } else { cur = list->head; while (cur->next != NULL) { cur = cur->next; } cur->next = item; } } list_node_t * list_remove(list_t * list, list_node_t * item) { list_node_t *cur; if (list_empty(list)) return NULL; if (list->head->data == item->data) { list_node_t * removed = list->head; list->head = list->head->next; return removed; } cur = list->head; assert(cur != NULL); while (cur->next != NULL) { if (cur->next->data == item->data) { list_node_t * removed = cur->next; cur->next = cur->next->next; return removed; /* just the first */ } cur = cur->next; } return NULL; } void list_revert(list_t *list) { /* FIXME: work without 'reverted?' */ list_t reverted; reverted.head = NULL; list_node_t *cur = list->head; while (cur != NULL) { list_node_t *next = cur->next; list_node_t *headbefore = reverted.head; reverted.head = cur; cur->next = headbefore; cur = next; } list->head = reverted.head; } list_node_t* list_elementat(list_t *list, int i) { if (list_empty(list) || i > list_length(list)-1) { return NULL; } list_node_t *cur = list->head; for (int j=0; j < i; j++) { cur = cur->next; } return cur; } int main(int argc, char *argv[]) { /* Test empty list */ list_t *emptylist = malloc(sizeof(list_t)); list_init(emptylist); assert(list_length(emptylist) == 0); assert(list_empty(emptylist) == true); list_print(emptylist); printf("list_length = %d\n", list_length(emptylist)); assert(list_elementat(emptylist, 0) == NULL); assert(list_elementat(emptylist, 1) == NULL); assert(list_elementat(emptylist, 2) == NULL); free(emptylist); /* Setup foolist for the following tests. */ list_t *foolist = malloc(sizeof(list_t)); list_init(foolist); /* Add one element */ list_node_t * foo = malloc(sizeof(list_node_t)); assert(foo != NULL); *foo = (list_node_t) { 1, NULL }; list_add(foolist, foo); assert(list_length(foolist) == 1); assert(list_empty(foolist) == false); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // append something to foo list_node_t * bar = malloc(sizeof(list_node_t)); *bar = (list_node_t) { 23, NULL }; list_add(foolist, bar); assert(list_length(foolist) == 2); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // append more const int howmany = 100; for (int i = 0; i < howmany; i++) { list_node_t *newnode = malloc(sizeof(list_node_t)); *newnode = (list_node_t) { i, NULL }; list_add(foolist, newnode); } assert(list_length(foolist) == 2 + howmany); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // remove something list_node_t toremove = { 23, NULL }; free(list_remove(foolist, &toremove)); assert(list_length(foolist) == 2 + howmany - 1); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // remove last item toremove.data = howmany - 1; free(list_remove(foolist, &toremove)); assert(list_length(foolist) == 2 + howmany - 2); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // remove something toremove.data = 1; free(list_remove(foolist, &toremove)); assert(list_length(foolist) == 2 + howmany - 3); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); // remove something toremove.data = 1; free(list_remove(foolist, &toremove)); assert(list_length(foolist) == 2 + howmany - 4); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); /* remove everything */ for (int i = 0; i < howmany; i++) { toremove.data = i; free(list_remove(foolist, &toremove)); } assert(list_length(foolist) == 0); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); /* remove last remaining item */ toremove.data = 2; list_remove(foolist, &toremove); assert(list_length(foolist) == 0); assert(list_empty(foolist) == true); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); /* revert a list */ const int howmany2 = 10; for (int i = 0; i < howmany2; i++) { list_node_t *newnode = malloc(sizeof(list_node_t)); newnode->data = i; newnode->next = NULL; list_add(foolist, newnode); } for (int i = 0; i < howmany2; i++) { list_node_t *el = list_elementat(foolist, i); assert(el->data == i); } assert(list_length(foolist) == howmany2); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); list_revert(foolist); for (int i = 0; i < howmany2; i++) { list_node_t *el = list_elementat(foolist, i); assert(el->data == howmany2-i-1); } assert(list_length(foolist) == howmany2); list_print(foolist); printf("list_length = %d\n", list_length(foolist)); /* Test upper bound */ assert(list_elementat(foolist, list_length(foolist)-1) != NULL); assert(list_elementat(foolist, list_length(foolist) ) == NULL); assert(list_elementat(foolist, list_length(foolist)+1) == NULL); assert(list_elementat(foolist, list_length(foolist)+2) == NULL); /* Free up remaining items and the list. */ while(!list_empty(foolist)) { list_node_t *el = list_elementat(foolist, 0); free(list_remove(foolist, el)); } free(foolist); }