1
0
Fork 0

More tests and documentation and utilities.

This commit is contained in:
wael 2021-09-08 21:55:17 +03:00
parent 29d32a612f
commit 9cf9159e4b
7 changed files with 263 additions and 9 deletions

View File

@ -0,0 +1,47 @@
.DA
.TL
single_linked_list.h
.AU
Wael Karram
.AB no
Documentation for single_linked_list.h
.AE
.ND
.PP
This header defines a linked list, with one link per node. Using the prepoccessor variable SINGLE_LINKED_LIST_H used as an include guard.
.br
Relies on single_node.h to implement the nodes.
.PP
These are the compile-time constants declared by this header:
.br
SUCCESS_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function on succcess, evaluates to 1.
.br
FAILURE_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function on failure, evaluates to 0.
.br
INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function when a requested index is not found, evaluates to -1.
.br
INVALID_INPUT_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function when recieving invalid input, evaluates to -2.
.br
CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C, this code is returned when freeing the data is successful, but the list is maformed, evaluates to -1.
.br
INDEX_HEAD_LINKED_LIST, this is the index of the head of the linked list, evaluates to 0.
.PP
These are the function defitions and input arguments for this data structre.
.br
Defines a single struct
.UL node_t \0which
has the fields
.I "next" \0and
.I "data" ,
the former of which is another node pointer, and the latter is a void pointer.
.br
It is of note that this header type-defines the aformentioned node as
.I "node_t" .

View File

@ -34,9 +34,26 @@ INDEX_HEAD_LINKED_LIST, this is the index of the head of the linked list, evalua
.PP
These are the function defitions and input arguments for this data structre.
These are the function defitions and input arguments for this data structre:
.br
Defines a single struct
linked_list* initialize_single_linked_list(): initializes an empty linked list, returns NULL on failure.
.br
int append_node_single_linked_list(linked_list_t *list, node_t *node): appends the node to the given list, returns success if worked, otherwise failure code is returned.
.br
int prepend_node_single_linked_list(linked_list_t *list, node_t *node): prepends the node to the given list, returns success if worked, otherwise failure code is returned.
.br
int append_node_data_single_linked_list(linked_list_t *list, void *data): much like the node appending function, but creates the node itself - note that the data can be NULL, will also return failure code when allocation of the node fails.
.br
int prepend_node_data_single_linked_list(linked_list_t *list, void *data): much like the node prepending function, but creates the node itself - note that the data can be NULL, will also return failure code when allocation of the node fails.
.br
int add_node_i_single_linked_list(linked_list_t *list, node_t *node, int i): much like append node, but might also fail when the index is invalid (returning the aforementioned error code).
.br
int add_node_data_i_single_linked_list(linked_list_t *list, void *data, int i): much like the node insertion function, but also attempts to allocate a node and put the data in it beforehand, will fail with the failure error code if allocation fails.
.br
void* read_node_i_songle_linked_list(linked_list_t *list, int i): attempts to return the stored data at the ith node, will return NULL if the list is NULL or index is invalid.
.br
.UL node_t \0which
has the fields
.I "next" \0and

View File

@ -40,9 +40,11 @@ node_t* pop(stack_t *stack) {
/* This function "peeks" at the top of the stack, will return NULL on error (in input/internal). */
const void* peek(stack_t *stack) {
/* Sanity check. */
if (stack == NULL)
if (stack == NULL || stack->head == NULL)
return NULL;
/* Return the data in the head. */
return stack->head->data;
}
/* This function pushes a node in, returns PUSH_SUCCESS on succes and PUSH_FAIL on failure. */

View File

@ -4,6 +4,7 @@
#define STRZCPY_C
/* Include statements. */
#include "strzcpy.h"
#endif //STRZCPY_C
/**
* This function takes a destination buffer, a source buffer and a length.
@ -17,5 +18,3 @@ char *strzcpy(char *restrict dst, const char* restrict src, size_t len) {
dst[len - 1] = '\0';
return end;
}
#endif //STRZCPY_C

View File

@ -0,0 +1,177 @@
/* Include statements. */
#include <stdio.h>
#include <assert.h>
#include "../linked_lists/double_linked_list.c"
/* Define constants. */
#define PRINT_INFO_TESTING_START "Starting tests.\n"
#define PRINT_INFO_TESTING_END "Done testing.\n"
#define ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION "Long list test failed because of allocation errors!\n"
#define SOME_TEST_FAILED "Recheck the tests, one of them failed!\n"
#define FUNCTION_ERROR "Some function encountered a data error in testing.\n"
#define INITIAL_LIST_LENGTH 0
#define LIST_LENGTH_ONE 1
#define LIST_LENGTH_LONG_TEST 4096
/* Define functions. */
double_node_t* generate_random_node();
double_linked_list_t* generate_long_random_list(int length);
int list_count_length(double_linked_list_t *list);
int test_linked_lists();
/* Starting point. */
int main() {
printf(PRINT_INFO_TESTING_START);
if (test_linked_lists()) {
printf(SOME_TEST_FAILED);
}
printf(PRINT_INFO_TESTING_END);
}
/* This function generates a random number and puts it in a newly allocated node. */
/* Caller has to free memory afterwards, returns NULL on failure. */
double_node_t* generate_random_node() {
/* The node to return. */
double_node_t* result;
int *value;
/* Attempt to allocate the node. */
result = (double_node_t*) malloc(sizeof(double_node_t));
if (result == NULL)
return NULL;
value = (int*) malloc(sizeof(int));
if (value == NULL) {
free(result);
return NULL;
}
*value = random();
/* Store and return. */
result->next = NULL;
result->previous = NULL;
result->data = value;
return result;
}
/* This function generates a long list with random values in the nodes, returns NULL on failures. */
/* Length denotes the length of the list. */
double_linked_list_t* generate_long_random_list(int length) {
/* Sanity check. */
if (length <= 0)
return NULL;
/* Variables. */
double_linked_list_t *list;
double_node_t *current;
int i;
/* Allocate the list. */
list = initialize_double_linked_list();
if (list == NULL)
return NULL;
/* Fill the list with random nodes. */
/* First node. */
current = generate_random_node();
if (current == NULL) {
free(list);
return NULL;
}
/* Attempt to append. */
if (!append_node_double_linked_list(list, current)) {
free(current->data);
free(current);
free(list);
return NULL;
}
/* Loop and add the rest. */
for (i = 1; i < length; i++) {
/* Generate and attempt to append. */
current = generate_random_node();
if (!append_node_double_linked_list(list, current)) {
/* Abort. */
free(current->data);
free(current);
clear_list_data_double_linked_list(&list, NULL);
return NULL;
}
}
/* Update the list's length. */
list->length = length;
/* Return the result. */
return list;
}
/* This function checks the actual length of a list. */
int list_count_length(double_linked_list_t *list) {
if (list == NULL || list->head == NULL)
return 0;
/* Loop and count. */
double_node_t *current = list->head;
int count = 0;
while (current != NULL) {
count++;
current = current->next;
}
/* Return the result. */
return count;
}
/* This function does the testing. */
int test_linked_lists() {
/* Local variables. */
double_linked_list_t *list;
double_node_t *node, *tail;
int error;
/* Initialize an empty list. */
list = initialize_double_linked_list();
/* Check that it was correctly created. */
assert(list != NULL);
assert(list->length == INITIAL_LIST_LENGTH);
assert(list->head == NULL);
assert(list->tail == NULL);
/* Generate and store the node. */
node = generate_random_node();
/* Attempt to add it to the list. */
append_node_double_linked_list(list, node);
/* Check that the list grew and that both the head and tail got set. */
assert(list->length == LIST_LENGTH_ONE);
assert(list->head != NULL && list->head == node);
assert(list->tail != NULL && list->tail == node);
assert(get_node_i_double_linked_list(list, 0, &error) == node);
if (!error)
printf(FUNCTION_ERROR);
assert(get_node_index_pointer_double_linked_list(list, node) == 0);
/* Attempt to free the nodes and then the list. */
remove_node_i_data_double_linked_list(list, 0, NULL);
assert(list->length == INITIAL_LIST_LENGTH);
assert(list->head == NULL);
node = NULL;
free(list);
list = NULL;
/* Attempt to allocate a long list. */
list = generate_long_random_list(LIST_LENGTH_LONG_TEST);
if (list == NULL) {
printf(ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION);
return 1;
}
assert(list->length == LIST_LENGTH_LONG_TEST);
assert(list->length == list_count_length(list));
/* Test the get head/tail functions. */
assert(get_node_head_double_linked_list(list) == list->head);
tail = get_node_tail_double_linked_list(list);
assert(tail != NULL && tail->next == NULL);
/* Test the indexer functions. */
assert(get_node_index_pointer_double_linked_list(list, tail) == (list->length - 1));
/* Test the freeing functions. */
clear_list_data_double_linked_list(&list, NULL);
assert(list == NULL);
/* Ran successfully, return 0. */
return 0;
}

View File

@ -17,7 +17,7 @@
/* Define functions. */
tree_node_t* generate_random_tree_node();
int comparison_function_int(int *first, int *second);
int comparison_function_int(const void *first, const void *second);
tree_node_t* insert_sorted_array_into_tree(int *array, int start, int end);
tree_node_t* build_tree(int **arr);
int check_tree_bst(tree_node_t *root, int (*comparison_function)());
@ -59,8 +59,8 @@ tree_node_t* generate_random_tree_node() {
}
/* This function is used to compare two integers (given their pointers), exhibits undefined behaviour on NULL pointers. */
int comparison_function_int(int *first, int *second) {
return *first == *second ? TREE_COMPARISON_EQUAL_TO : ((*first < *second) ? TREE_COMPARISON_SMALLER_THAN : TREE_COMPARISON_LARGER_THAN);
int comparison_function_int(const void *first, const void *second) {
return *((int*)first) == *((int*)second) ? TREE_COMPARISON_EQUAL_TO : ((*((int*)first) < *((int*)second)) ? TREE_COMPARISON_SMALLER_THAN : TREE_COMPARISON_LARGER_THAN);
}
/* This function will generate a balanced tree from the given sorted array, returns the root. */

12
utils/time_function.h Normal file
View File

@ -0,0 +1,12 @@
/* This header defines a struct for storing function timing information. */
#ifndef TIME_FUNCTION_H
#define TIME_FUNCTION_H
/* Struct used to store the results. */
typedef struct function_run_time {
/* Function name. */
char *name;
/* Length of run time. */
double time;
} function_run_time;
#endif /* TIME_FUNCTION_H */