You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.1 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#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(void) {
/* 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);
}