/* * model.h * * Created on: 19/02/2009 * Author: mateu hunter */ #ifndef HELPERS_H_ #define HELPERS_H_ #include <string.h> #define MAX_LIST_LENGTH 100 struct node { char *first_name; char *last_name; struct node *next; struct node *previous; }; #define VERBOSE_HEADER 0 #define DEBUG_HEADER 0 /* Function Signatures */ int pointer_is_NULL(struct node *ptr); int is_head(struct node *head); int number_of_nodes(struct node *head); struct node* create_initial_node(char *first_name, char *last_name); struct node* add_node(struct node *head, char *first_name, char *last_name, int position); struct node* add_node_head(struct node *head, char *first_name, char *last_name, int position); struct node* add_node_tail(struct node *head, char *first_name, char *last_name, int position); struct node* add_node_between(struct node *head, char *first_name, char *last_name, int position); struct node* position_cursor(struct node *head, int position); struct node* get_node(struct node *head, int position); struct node* get_tail_node(struct node *head); struct node* delete_node(struct node *head, int position); struct node* delete_node_head(struct node *head); struct node* delete_node_tail(struct node *head); struct node* delete_node_between(struct node *head, int position); struct node* free_all_nodes(struct node *head); void search_nodes(struct node *head, char search_field, char *search_term); struct node* reverse_nodes(struct node *head); struct node* sort_nodes(struct node *head, int sort_type); void print_all_nodes(struct node *head); void not_head_message(void); void pointer_is_NULL_message(void); /* Since we are, by convention, passing and returning the head node * to most all these non-void arg functions, we are assuming we always have * access to head or the programmer screwed up. Thus the first element, * head, is alway around, and I'm not going to write a function * head = get_head(head); */ /* Function Definitions */ struct node* create_initial_node(char *first_name, char *last_name) { struct node *tmp = (struct node*) malloc(sizeof(struct node)); tmp->first_name = first_name; tmp->last_name = last_name; tmp->next = NULL; tmp->previous = NULL; return tmp; } struct node* add_node(struct node *head, char *first_name, char *last_name, int position) { /* insert at head */ if (position == 0) { head = add_node_head(head, first_name, last_name, position); } /* insert at tail */ else if (position == number_of_nodes(head)) { head = add_node_tail(head, first_name, last_name, position); } /* insert between two nodes */ else if (position > 0 && position < number_of_nodes(head)) { head = add_node_between(head, first_name, last_name, position); } else { printf("Warning: you entered a position number out of range: %d.\n", position); printf("No action taken.\n"); free(first_name); free(last_name); /* exit(-1); */ } return head; } struct node* add_node_between(struct node *head, char *first_name, char *last_name, int position) { struct node *tmp = (struct node*) malloc(sizeof(struct node)); struct node *cursor = NULL; if (is_head(head)) { cursor = position_cursor(head, position); if (VERBOSE_HEADER) { printf("We have a tween case.\n"); } tmp->first_name = first_name; tmp->last_name = last_name; tmp->previous = cursor; tmp->next = cursor->next; cursor->next->previous = tmp; cursor->next = tmp; return head; } else { not_head_message(); exit(-1); } } struct node* add_node_head(struct node *head, char *first_name, char *last_name, int position) { struct node *tmp = (struct node*) malloc(sizeof(struct node)); if (is_head(head)) { if (VERBOSE_HEADER) { printf("We have a head case.\n"); } tmp->first_name = first_name; tmp->last_name = last_name; tmp->next = NULL; tmp->previous = head; tmp->previous->next = tmp; /* tmp is new head */ return tmp; } else { not_head_message(); exit(-1); } } struct node* add_node_tail(struct node *head, char *first_name, char *last_name, int position) { struct node *tmp = (struct node*) malloc(sizeof(struct node)); struct node *cursor = NULL; if (is_head(head)) { if (VERBOSE_HEADER) { printf("We have a tail case.\n"); } cursor = position_cursor(head, position - 1); tmp->first_name = first_name; tmp->last_name = last_name; tmp->previous = NULL; tmp->next = cursor; tmp->next->previous = tmp; return head; } else { not_head_message(); exit(-1); } } int pointer_is_NULL(struct node *ptr) { int the_truth; if (VERBOSE_HEADER) { printf("Is the pointer NULL?\n"); } the_truth = ptr == NULL ? 1 : 0; return the_truth; } int is_head(struct node *head) { if (VERBOSE_HEADER) { printf("Is head?\n"); } if (head == NULL) { if (DEBUG_HEADER) { printf("pointer IS NULL.\n"); } return 0; } else if (head->next == NULL) { if (DEBUG_HEADER) { printf("head->next is NULL, got head."); } return 1; } else { if (DEBUG_HEADER) { printf("head->next is not NULL, not got head."); } return 0; } } int number_of_nodes(struct node *head) { int number_of_nodes = 0; struct node *cursor = NULL; if (VERBOSE_HEADER) { printf("Calculating number of nodes...\n"); } /* Make sure we got real head */ if (is_head(head)) { cursor = head; number_of_nodes = 1; while ( (cursor = cursor->previous) ) { number_of_nodes++; } } return number_of_nodes; } /* Position is zero based (i.e. position 0 is for the 1st element) */ struct node* position_cursor(struct node *head, int position) { int i = 0; struct node *cursor = NULL; cursor = head; for (; (i < position) && (i < number_of_nodes(head)); i++) { cursor = cursor->previous; } return cursor; } struct node* get_tail_node(struct node *head) { return position_cursor(head, number_of_nodes(head) - 1); } struct node* get_node(struct node *head, int position) { return position_cursor(head, position); } struct node* delete_node(struct node *head, int position) { /* Handle NULL case with slight grace */ if (head == NULL) { pointer_is_NULL_message(); } /* delete head */ if (position == 0) { /* printf("Deleting head.\n"); */ head = delete_node_head(head); } /* delete tail */ else if (position == number_of_nodes(head) - 1) { head = delete_node_tail(head); } /* delete a node between two nodes */ else if (position > 0 && position < number_of_nodes(head) - 1) { head = delete_node_between(head, position); } else { printf( "Warning: you entered a position number out of range: %d.\nNo action taken.\n", position); /* exit(-1); */ } return head; } struct node* delete_node_head(struct node *head) { if (number_of_nodes(head) == 0) { printf("Given empty list. You expecting something else?\n"); return NULL; } else if (number_of_nodes(head) == 1) { if (VERBOSE_HEADER) { printf("Given one item list.\n"); } free(head->first_name); free(head->last_name); free(head); return NULL; } else { struct node *cursor; if (VERBOSE_HEADER) { printf("Given multiple item list.\n"); } cursor = head->previous; cursor->next = NULL; free(head->first_name); free(head->last_name); free(head); /* cursor is new head */ return cursor; } } /* Delete nodes but not names */ struct node* delete_cursor_head(struct node *head) { if (number_of_nodes(head) == 0) { printf("Given empty list. You expecting something else?\n"); return NULL; } else if (number_of_nodes(head) == 1) { if (VERBOSE_HEADER) { printf("Given one item list.\n"); } free(head); return NULL; } else { struct node *cursor; if (VERBOSE_HEADER) { printf("Given multiple item list.\n"); } cursor = head->previous; cursor->next = NULL; free(head); /* cursor is new head */ return cursor; } } struct node* delete_node_tail(struct node *head) { if (head == NULL) { return NULL; } else if (number_of_nodes(head) == 1) { free(head->first_name); free(head->last_name); free(head); return NULL; } else { struct node *tail; struct node *cursor; tail = get_tail_node(head); cursor = tail->next; cursor->previous = NULL; free(tail->first_name); free(tail->last_name); free(tail); return head; } } /* use of tweener to label a node between two others * origins trivia: a basketball player caught between two positions. * e.g D.J. may be a tweener in the NBA because he's not a * true power forward at that level, nor is he a small forward. */ struct node* delete_node_between(struct node *head, int position) { struct node *tweener_node = NULL; tweener_node = get_node(head, position); tweener_node->next->previous = tweener_node->previous; tweener_node->previous->next = tweener_node->next; free(tweener_node->first_name); free(tweener_node->last_name); free(tweener_node); return head; } struct node* free_all_nodes(struct node *head) { int i = 0; int total_number_of_nodes = number_of_nodes(head); if (number_of_nodes(head) == 1) { /* Just have head to free */ free(head->first_name); free(head->last_name); free(head); } else { for (; i < total_number_of_nodes; i++) { /* Keep chopping of the head 'til there is no more. * Doesn't seem efficient since we really just need to * free all the nodes and not relink new head each time, * but delete_node() was already written and available * for reuse. * */ if (DEBUG_HEADER) { printf("Head is %s %s.\n", head->first_name, head->last_name); } head = delete_node(head, 0); } } return head; } /* Used to free up node pointers but leave names around * Useful for reverse and could be used with sort. */ struct node* free_all_cursors(struct node *head) { int i = 0; int total_number_of_nodes = number_of_nodes(head); if (number_of_nodes(head) == 1) { /* Just have head to free */ free(head); } else { for (; i < total_number_of_nodes; i++) { /* Keep chopping of the head 'til there is no more. * Doesn't seem efficient since we really just need to * free all the nodes and not relink new head each time, * but delete_node() was already written and available * for reuse. * */ if (DEBUG_HEADER) { printf("Head is %s %s.\n", head->first_name, head->last_name); } head = delete_cursor_head(head); } } return head; } void search_nodes(struct node *head, char search_field, char *search_term) { struct node *cursor = NULL; int someone_found = 0; /* Do we have a proper list? */ if (is_head(head)) { cursor = head; /* Handle search on first name */ do { if (search_field == 'f') { if (strcmp(cursor->first_name, search_term) == 0) { someone_found = 1; printf("Found person with matching first name: %s %s\n", cursor->first_name, cursor->last_name); } } else if (search_field == 'l') { if (strcmp(cursor->last_name, search_term) == 0) { someone_found = 1; printf("Found person with matching last name: %s %s\n", cursor->first_name, cursor->last_name); } } } while ( (cursor = cursor->previous) ); } if (!someone_found) { printf("No one found matching: %s\n", search_term); } } struct node * reverse_nodes(struct node *head) { struct node *new_head = NULL; struct node *cursor = NULL; struct node *tail = NULL; int i; /* return head when list has only one element */ if (number_of_nodes(head) == 1) { return head; } tail = get_tail_node(head); cursor = tail; /* create one headed monster */ new_head = create_initial_node(tail->first_name, tail->last_name); /* add tweener nodes */ for (i = 1; i < number_of_nodes(head) - 1; i++) { cursor = cursor->next; new_head = add_node(new_head, cursor->first_name, cursor->last_name, i); } /* add new tail */ new_head = add_node_tail(new_head, head->first_name, head->last_name, number_of_nodes(head) - 1); free_all_cursors(head); return new_head; } struct node * sort_nodes(struct node *head, int sort_type) { struct node *new_head = NULL; struct node *cursor = NULL; struct node *new_cursor = NULL; int i, j, node_sorted; /* return head when list has only one element */ if (number_of_nodes(head) == 1) { return head; } cursor = head; /* create one headed monster */ new_head = create_initial_node(head->first_name, head->last_name); /* add tweener nodes */ for (i = 1; i < number_of_nodes(head) - 1; i++) { cursor = cursor->previous; new_cursor = new_head; node_sorted = 0; /* check current un-sorted node against sorted nodes */ for (j = 0; j < number_of_nodes(new_head); j++) { if (strcmp(cursor->first_name, new_cursor->first_name) == -1) { new_head = add_node(new_head, cursor->first_name, cursor->last_name, j); node_sorted = 1; break; } new_cursor = new_cursor->previous; } /* put node at tail if it's not less than any other */ if (!node_sorted) { new_head = add_node_tail(new_head, cursor->first_name, cursor->last_name, number_of_nodes(new_head)); } } /* add new tail */ free_all_cursors(head); return new_head; } /* Print functions */ void print_all_nodes(struct node *head) { struct node *cursor = NULL; cursor = head; do { printf("My name is %s %s.\n", cursor->first_name, cursor->last_name); } while ( (cursor = cursor->previous) ); } void not_head_message(void) { printf("ERROR. You did not give head.\n"); } void pointer_is_NULL_message(void) { printf( "Warning. Your node is empty. Maybe you want a more interesting node?\n"); } #endif /* HELPERS_H_ */
Showing changes from previous revision. Removed | Added
