S
Steve Lambert
Hi,
I've knocked up a number of small routines to create and manipulate a linked
list of any structure. If anyone could take a look at this code and give me
their opinion and details of any potential pitfalls I'd be extremely
grateful.
Cheers
Steve
ll.h
/*
USAGE NOTES FOR CALLING MODULES
-- include the linked list module header file
#include "ll.h"
-- declare any structure that is going to make up the linked list
eg.
struct PERSONAL_DETAILS
{
char forename[20];
char surname[20];
short house_number;
char street[20];
char town[20];
char county[20];
char phone[12];
};
-- declare a variable of this type
eg.
PERSONAL_DETAILS person;
-- declare a pointer to the linked list
eg
LINKED_LIST_TYPE *people = NULL;
-- create the actual linked list
eg
ll_create( &people ); NB The ADDRESS of the pointer is passed
-- populate your structure with appropriate details
eg
strcpy(person.forename, "steve");
strcpy(person.surname, "lambert");
etc ...
-- add the structure to the end of the linked list
eg
ll_append( people, &person, sizeof(PERSONAL_DETAILS) );
-- to loop through the linked list elements
-- reset internal linked list variables to point to the start of the
linked list
eg
ll_start( people );
-- loop through all the elements
eg
while ( ll_next(people) )
{
-- get the data
eg
people = (PERSONAL_DETAILS *)ll_data(people);
}
-- finally, deallocate all allocated memory
eg
ll_destroy( &people ); NB The ADDRESS of the pointer is passed
*/
struct NODE_TYPE
{
void *data;
NODE_TYPE *next;
};
struct LINKED_LIST_TYPE
{
NODE_TYPE *header;
NODE_TYPE *current_node;
NODE_TYPE *last_node;
long number_of_nodes;
long node_number;
};
void ll_create( LINKED_LIST_TYPE **ptr );
void ll_destroy( LINKED_LIST_TYPE **linked_list );
void ll_append( LINKED_LIST_TYPE *linked_list,
void *data,
size_t data_size );
short ll_start ( LINKED_LIST_TYPE *linked_list );
void *ll_data ( LINKED_LIST_TYPE *linked_list );
short ll_next ( LINKED_LIST_TYPE *linked_list );
ll.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ll.h"
#include "debug_refdec.h"
void ll_create( LINKED_LIST_TYPE **linked_list_ptr )
{
LINKED_LIST_TYPE *linked_list;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_create - start\n");
}
/* ****************************** */
/* allocate space for the linked list structure */
linked_list = (LINKED_LIST_TYPE *) malloc( sizeof(LINKED_LIST_TYPE) );
if ( !linked_list )
{
exit( EXIT_FAILURE );
}
//printf("Allocating linked list : %p\n",linked_list);
/* initialise the linked list elements */
linked_list->header = NULL;
linked_list->current_node = NULL;
linked_list->last_node = NULL;
linked_list->number_of_nodes = 0;
linked_list->node_number = 0;
*linked_list_ptr = linked_list;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_create - end\n");
}
/* ****************************** */
}
void ll_destroy( LINKED_LIST_TYPE **linked_list )
{
NODE_TYPE *current_node = NULL;
NODE_TYPE *next_node = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_destroy - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !*linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
current_node = (*linked_list)->header;
while ( current_node )
{
next_node = current_node->next;
//printf("Freeing node data : %p\n", current_node->data);
free( current_node->data );
//printf("Freeing node : %p\n", current_node);
free( current_node );
current_node = next_node;
}
//printf("freeing linked list : %p\n", *linked_list);
free( *linked_list );
*linked_list = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_destroy - end\n");
}
/* ****************************** */
}
void ll_append( LINKED_LIST_TYPE *linked_list,
void *data,
size_t data_size )
{
NODE_TYPE *new_node = NULL;
void *node_data = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_append - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* allocate space for the new node */
new_node = (NODE_TYPE *) malloc( sizeof(NODE_TYPE) );
if ( !new_node )
{
//printf("ERROR : failed to allocate space for new node\n");
exit( EXIT_FAILURE );
}
//printf("Allocating node : %p\n", new_node);
/* allocate space for the node data */
new_node->data = malloc( data_size );
if ( !new_node->data )
{
//printf("ERROR : failed to allocate space for new node data\n");
exit( EXIT_FAILURE );
}
//printf("allocating node data : %p\n", new_node->data);
/* copy the data to the node */
memcpy( new_node->data, data, data_size );
/* note that this is the last node in the linked list */
new_node->next = NULL;
/* append the node to the linked list */
if ( linked_list->number_of_nodes == 0 )
{
/* this is the first node in the linked list */
linked_list->header = new_node;
linked_list->last_node = new_node;
linked_list->number_of_nodes = 1;
}
else
{
/* add the node to the end of the linked list */
linked_list->last_node->next = new_node;
linked_list->last_node = new_node;
linked_list->number_of_nodes++;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_append - end\n");
}
/* ****************************** */
}
short ll_start ( LINKED_LIST_TYPE *linked_list )
{
short status;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_start - start\n");
}
/* ****************************** */
if ( !linked_list )
{
/* linked list has not been initialised */
status = 0;
}
else if ( linked_list->number_of_nodes == 0 )
{
/* linked list has no entries */
status = 0;
}
else
{
/* point to the start of the linked list */
linked_list->current_node = NULL;
linked_list->node_number = 0;
status = 1;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_start - end\n");
}
/* ****************************** */
return ( status );
}
void *ll_data ( LINKED_LIST_TYPE *linked_list )
{
/* ****************************** */
if (debug_level == 1)
{
printf("ll_data - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* check that the linked list has entries */
if ( linked_list->number_of_nodes == 0 )
{
//printf("ERROR : linked list has no data\n");
exit( EXIT_FAILURE );
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_data - end\n");
}
/* ****************************** */
return( linked_list->current_node->data );
}
short ll_next ( LINKED_LIST_TYPE *linked_list )
{
short status;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_next - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* check that the linked list has entries */
if ( linked_list->number_of_nodes == 0 )
{
//printf("ERROR : linked list has no data\n");
exit( EXIT_FAILURE );
}
if ( !linked_list->current_node )
{
/* at the start of the list */
linked_list->current_node = linked_list->header;
linked_list->node_number++;
status = 1;
}
else if ( linked_list->current_node != linked_list->last_node )
{
/* part way through the list */
linked_list->current_node = linked_list->current_node->next;
linked_list->node_number++;
status = 1;
}
else
{
/* at end of list */
status = 0;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_next - end : status = %d\n", status);
}
/* ****************************** */
return ( status );
}
I've knocked up a number of small routines to create and manipulate a linked
list of any structure. If anyone could take a look at this code and give me
their opinion and details of any potential pitfalls I'd be extremely
grateful.
Cheers
Steve
ll.h
/*
USAGE NOTES FOR CALLING MODULES
-- include the linked list module header file
#include "ll.h"
-- declare any structure that is going to make up the linked list
eg.
struct PERSONAL_DETAILS
{
char forename[20];
char surname[20];
short house_number;
char street[20];
char town[20];
char county[20];
char phone[12];
};
-- declare a variable of this type
eg.
PERSONAL_DETAILS person;
-- declare a pointer to the linked list
eg
LINKED_LIST_TYPE *people = NULL;
-- create the actual linked list
eg
ll_create( &people ); NB The ADDRESS of the pointer is passed
-- populate your structure with appropriate details
eg
strcpy(person.forename, "steve");
strcpy(person.surname, "lambert");
etc ...
-- add the structure to the end of the linked list
eg
ll_append( people, &person, sizeof(PERSONAL_DETAILS) );
-- to loop through the linked list elements
-- reset internal linked list variables to point to the start of the
linked list
eg
ll_start( people );
-- loop through all the elements
eg
while ( ll_next(people) )
{
-- get the data
eg
people = (PERSONAL_DETAILS *)ll_data(people);
}
-- finally, deallocate all allocated memory
eg
ll_destroy( &people ); NB The ADDRESS of the pointer is passed
*/
struct NODE_TYPE
{
void *data;
NODE_TYPE *next;
};
struct LINKED_LIST_TYPE
{
NODE_TYPE *header;
NODE_TYPE *current_node;
NODE_TYPE *last_node;
long number_of_nodes;
long node_number;
};
void ll_create( LINKED_LIST_TYPE **ptr );
void ll_destroy( LINKED_LIST_TYPE **linked_list );
void ll_append( LINKED_LIST_TYPE *linked_list,
void *data,
size_t data_size );
short ll_start ( LINKED_LIST_TYPE *linked_list );
void *ll_data ( LINKED_LIST_TYPE *linked_list );
short ll_next ( LINKED_LIST_TYPE *linked_list );
ll.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ll.h"
#include "debug_refdec.h"
void ll_create( LINKED_LIST_TYPE **linked_list_ptr )
{
LINKED_LIST_TYPE *linked_list;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_create - start\n");
}
/* ****************************** */
/* allocate space for the linked list structure */
linked_list = (LINKED_LIST_TYPE *) malloc( sizeof(LINKED_LIST_TYPE) );
if ( !linked_list )
{
exit( EXIT_FAILURE );
}
//printf("Allocating linked list : %p\n",linked_list);
/* initialise the linked list elements */
linked_list->header = NULL;
linked_list->current_node = NULL;
linked_list->last_node = NULL;
linked_list->number_of_nodes = 0;
linked_list->node_number = 0;
*linked_list_ptr = linked_list;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_create - end\n");
}
/* ****************************** */
}
void ll_destroy( LINKED_LIST_TYPE **linked_list )
{
NODE_TYPE *current_node = NULL;
NODE_TYPE *next_node = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_destroy - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !*linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
current_node = (*linked_list)->header;
while ( current_node )
{
next_node = current_node->next;
//printf("Freeing node data : %p\n", current_node->data);
free( current_node->data );
//printf("Freeing node : %p\n", current_node);
free( current_node );
current_node = next_node;
}
//printf("freeing linked list : %p\n", *linked_list);
free( *linked_list );
*linked_list = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_destroy - end\n");
}
/* ****************************** */
}
void ll_append( LINKED_LIST_TYPE *linked_list,
void *data,
size_t data_size )
{
NODE_TYPE *new_node = NULL;
void *node_data = NULL;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_append - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* allocate space for the new node */
new_node = (NODE_TYPE *) malloc( sizeof(NODE_TYPE) );
if ( !new_node )
{
//printf("ERROR : failed to allocate space for new node\n");
exit( EXIT_FAILURE );
}
//printf("Allocating node : %p\n", new_node);
/* allocate space for the node data */
new_node->data = malloc( data_size );
if ( !new_node->data )
{
//printf("ERROR : failed to allocate space for new node data\n");
exit( EXIT_FAILURE );
}
//printf("allocating node data : %p\n", new_node->data);
/* copy the data to the node */
memcpy( new_node->data, data, data_size );
/* note that this is the last node in the linked list */
new_node->next = NULL;
/* append the node to the linked list */
if ( linked_list->number_of_nodes == 0 )
{
/* this is the first node in the linked list */
linked_list->header = new_node;
linked_list->last_node = new_node;
linked_list->number_of_nodes = 1;
}
else
{
/* add the node to the end of the linked list */
linked_list->last_node->next = new_node;
linked_list->last_node = new_node;
linked_list->number_of_nodes++;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_append - end\n");
}
/* ****************************** */
}
short ll_start ( LINKED_LIST_TYPE *linked_list )
{
short status;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_start - start\n");
}
/* ****************************** */
if ( !linked_list )
{
/* linked list has not been initialised */
status = 0;
}
else if ( linked_list->number_of_nodes == 0 )
{
/* linked list has no entries */
status = 0;
}
else
{
/* point to the start of the linked list */
linked_list->current_node = NULL;
linked_list->node_number = 0;
status = 1;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_start - end\n");
}
/* ****************************** */
return ( status );
}
void *ll_data ( LINKED_LIST_TYPE *linked_list )
{
/* ****************************** */
if (debug_level == 1)
{
printf("ll_data - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* check that the linked list has entries */
if ( linked_list->number_of_nodes == 0 )
{
//printf("ERROR : linked list has no data\n");
exit( EXIT_FAILURE );
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_data - end\n");
}
/* ****************************** */
return( linked_list->current_node->data );
}
short ll_next ( LINKED_LIST_TYPE *linked_list )
{
short status;
/* ****************************** */
if (debug_level == 1)
{
printf("ll_next - start\n");
}
/* ****************************** */
/* check that the linked list has been initialised */
if ( !linked_list )
{
//printf("ERROR : linked list not initialised\n");
exit( EXIT_FAILURE );
}
/* check that the linked list has entries */
if ( linked_list->number_of_nodes == 0 )
{
//printf("ERROR : linked list has no data\n");
exit( EXIT_FAILURE );
}
if ( !linked_list->current_node )
{
/* at the start of the list */
linked_list->current_node = linked_list->header;
linked_list->node_number++;
status = 1;
}
else if ( linked_list->current_node != linked_list->last_node )
{
/* part way through the list */
linked_list->current_node = linked_list->current_node->next;
linked_list->node_number++;
status = 1;
}
else
{
/* at end of list */
status = 0;
}
/* ****************************** */
if (debug_level == 1)
{
printf("ll_next - end : status = %d\n", status);
}
/* ****************************** */
return ( status );
}