Here is some code I've written. I am welcoming any critiques, whether it is style/formatting, correctness (I believe it is correct) -- I would appreciate any advice on formatting unit tests, and any other thing that people may think of.
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
/*
* all functions expect a null-terminated C-string for argument "str"
*/
/*
* a node in the linked list
*/
struct ll_node
{
char* str;
struct ll_node *prev;
struct ll_node *next;
};
/*
* the "manager" of the linked list
*/
struct ll_node_manager
{
struct ll_node *head;
struct ll_node *tail;
};
/*
* initialize the linked list
*/
void
init_ll (struct ll_node_manager *ptr)
{
ptr->head = NULL;
ptr->tail = NULL;
}
/*
* insert node at head of linked list
* return false on failure (allocation error) or true otherwise
*/
bool
insert_head_ll (struct ll_node_manager *ptr, char *str)
{
if (!ptr->head)
{
ptr->head = malloc(sizeof(struct ll_node));
if (!ptr->head)
return false;
ptr->tail = ptr->head;
ptr->head->str = strdup(str);
if (!ptr->head->str)
return false;
ptr->head->prev = NULL;
ptr->head->next = NULL;
}
else
{
struct ll_node *tmp = malloc(sizeof(struct ll_node));
if (!tmp)
return false;
tmp->str = strdup(str);
if (!tmp->str)
return false;
tmp->prev = NULL;
tmp->next = ptr->head;
ptr->head->prev = tmp;
ptr->head = tmp;
}
return true;
}
/*
* insert node at tail of linked list
* return false on failure (allocation error) or true otherwise
*/
bool
insert_tail_ll(struct ll_node_manager *ptr, char *str)
{
if (!ptr->tail)
{
ptr->head = malloc(sizeof(struct ll_node));
if (!ptr->head)
return false;
ptr->tail = ptr->head;
ptr->head->str = strdup(str);
if (!ptr->head->str)
return false;
ptr->head->prev = NULL;
ptr->head->next = NULL;
}
else
{
struct ll_node *tmp = malloc(sizeof(struct ll_node));
if (!tmp)
return false;
tmp->str = strdup(str);
if (!tmp->str)
return false;
tmp->prev = ptr->tail;
tmp->next = NULL;;
ptr->tail->next = tmp;
ptr->tail = tmp;
}
return true;
}
/*
* return true if node with value of "str" contained in linked list
* return false otherwise
*/
bool
ll_contains(struct ll_node_manager *ptr, char *str)
{
for (struct ll_node *tmp = ptr->head;
tmp; tmp = tmp->next)
if (strcmp(tmp->str, str) == 0)
return true;
return false;
}
/*
* return true if successful (removed head)
* return false if not (did not exist)
*/
bool
remove_head_ll(struct ll_node_manager *ptr)
{
if (!ptr->head)
return false;
struct ll_node *tmp = ptr->head;
ptr->head = ptr->head->next;
if (!ptr->head)
ptr->tail = ptr->head;
free(tmp->str);
free(tmp);
return true;
}
/*
* return true if successful (removed tail)
* return false if not (did not exist)
*/
bool
remove_tail_ll(struct ll_node_manager *ptr)
{
if (!ptr->tail)
return false;
struct ll_node *tmp = ptr->tail;
ptr->tail = ptr->tail->prev;
if (!ptr->tail)
ptr->head = ptr->tail;
free(tmp->str);
free(tmp);
return true;
}
/*
* remove first node (traverse from head) with value of "str"
* return true if successful (node found and removed)
* return false if not (node not found)
*/
bool
remove_node_ll(struct ll_node_manager *ptr, char *str)
{
for (struct ll_node *tmp = ptr->head;
tmp; tmp = tmp->next)
if (strcmp(tmp->str, str) == 0)
{
tmp->prev->next = tmp->next;
tmp->next->prev = tmp->prev;
free(tmp->str);
free(tmp);
return true;
}
return false;
}
I am a relative beginner. A second year Computer Science student in university. I'm practicing implementing data structures for my own knowledge.