You may want to split your phone list into at least two pieces: the linked list and everything else. By extracting (refactoring) your linked list from your phone list, you can use the list for other assignments (tasks).
Also, with linked list code, macros and #define
do not work well. Using #define
to reduce your typing is actually a hindrance to developing your code. In your example (as posted), the NEXT
is difficult to debug, especially if there is an error in it.
Here is some code to help you in your quest:
Data Structures
struct Single_Link
{
void * p_node_data; // Points to the user's data
struct Single_Link * p_next;
};
/* Optionally for doubly linked list: */
struct Double_Link
{
void * p_node_data;
struct Double_Link * p_next;
struct Double_Link * p_previous;
};
struct Single_List_Header
{
struct Single_Link * p_first_node;
struct Single_Link * p_last_node; // Points to last node for easy appending.
unsigned int nodes_in_list; // For quick access to size of the list.
};
Generic Functions
void Linked_List_Initialize(struct Single_List_Header * p_header)
{
if (p_header)
{
p_header->p_first_node = 0;
p_header->p_last_node = 0;
nodes_in_list = 0;
}
return;
}
void Linked_List_Insert_No_Sort(struct Single_List_Header * p_header,
void * p_node_data)
{
if (p_header)
{
// Create new node
struct Single_Link p_new_node = malloc(sizeof(struct Single_Link));
if (p_new_node)
{
// Initialize the new node.
p_new_node->p_next = 0;
p_new_node->p_node_data = p_node_data;
// Insert node to beginning of list
if (p_header->p_last_node == 0)
{
p_header->p_last_node = p_new_node;
}
p_new_node->p_next = p_header->p_first_node;
p_header->p_first_node = p_new_node;
++(p_header->nodes_in_list);
}
}
return;
}
typedef void (*Callback_Function_Ptr)(void * p_node_data);
void Linked_List_Traverse(struct Single_List_Header * p_header,
Callback_Function_Ptr user_function)
{
struct Single_Link * p_node = 0;
if (!p_header || ! user_function)
{
return;
}
if ((p_header->nodes_in_list == 0) || (!p_header->p_first_node))
{
return;
}
p_node = p_header->p_first_node;
while (p_node)
{
user_function(p_node->p_node_data);
p_node = p_node->p_next;
}
return;
}
}
Summary
The data structures and functions above have no reference to specialized or specific data. The data in a node is referenced by a pointer, more succinctly, a pointer to void
. This allows the Linked List data structure to be used by other entities, such as a Phone List, a List of Songs, etc.
By factoring out the specialization, the development is focused on the Linked List. No worrying about User I/O or data integrity. Also, once this works, it will not have to be debugged for your other assignments (projects). Just place it in its own translation unit (or compile to a library). No more wasting time developing a new Linked List.
BTW, another time saving tip is to search Stack Overflow or the web before posting any questions. Most likely, somebody else has encountered the same issue or something close. Also, there may be code out there that has already been tested, so you don't have to develop new code.