/* File: list1.c Implementation of a simple linked list ADT */ #include #include #include "string.h" #include "list1.h" /* Private Function Prototypes */ static void CrashOnNull(void *, char *) ; static node *NewNode(char *) ; static void FreeNode(node *ptr) ; /* Private Function Implementations */ /* Exit if ptr is NULL. */ static void CrashOnNull(void *ptr, char *mesg) { if (ptr == NULL) { fprintf(stderr, "%s\n", mesg) ; exit(1) ; } } /* Make a new node with given item and next field set to NULL */ static node *NewNode(char *item) { node *new ; new = (node *) malloc (sizeof(node)) ; CrashOnNull(new, "cannot make new node") ; if (item == NULL) item = "" ; new->item = strdup(item) ; CrashOnNull(new->item, "cannot duplicate string") ; new->next = NULL ; return new ; } /* Free memory allocated to the node */ static void FreeNode(node *ptr) { if (ptr->item != NULL) free(ptr->item) ; free(ptr) ; } /* Public Functions */ /* Make a new list */ list CreateList (void) { list NewL ; NewL = (list) malloc(sizeof (*NewL)) ; CrashOnNull(NewL, "cannot make new list") ; NewL->header.item = NULL ; NewL->header.next = NULL ; NewL->count = 0 ; NewL->last = &NewL->header ; return NewL ; } /* Add item to the end of the list */ void Append(list L, char *item) { node *new ; new = NewNode(item) ; L->last->next = new ; L->last = new ; L->count++ ; } /* Add item to the beginning of the list */ void Prepend(list L, char *item) { node *new ; new = NewNode(item) ; new->next = L->header.next ; L->header.next = new ; L->count++ ; if (new->next == NULL) L->last = new ; } /* Does item with key appear on the list? 0=No 1=Yes */ int IsMember(list L, char *key) { node *current ; current = L->header.next ; while(current != NULL) { if (strcmp(current->item, key) == 0) return 1 ; current = current->next ; } return 0 ; } /* Return the position in the list of the item with key or NULL if no such item. Note: position is actually the pointer to the node before the item with the key. This position is suitable for use with Delete() below as long as the list has not been modified. */ node *Locate(list L, char *key) { node *prev ; prev = &L->header ; while(prev->next != NULL) { if (strcmp(prev->next->item, key) == 0) { return prev ; } prev = prev->next ; } return NULL ; } /* Remove item in given position from the list. See note regarding position in documentation for Locate(). */ void Delete(list L, node *position) { node *temp ; if (position == NULL || position->next == NULL) return ; temp = position->next ; position->next = position->next->next ; FreeNode(temp) ; /* previous version leaked memory */ L->count-- ; /* Check if we deleted the last node */ if (position->next == NULL) L->last = position ; } /* Add list L2 to the end of list L1. L2 is destroyed. */ void Concatenate(list L1, list L2) { L1->count += L2->count ; L1->last->next = L2->header.next ; if (L1->last->next != NULL) { L1->last = L2->last ; } free(L2) ; /* previous version leaked memory */ } /* Duplicate of the list. All items and nodes have newly allocated memory. */ list ListDup(list L) { list NewL ; node *copyto, *copyfrom ; NewL = CreateList() ; NewL->count = L->count ; copyto = &NewL->header ; copyfrom = L->header.next ; while(copyfrom != NULL) { copyto->next = NewNode(copyfrom->item) ; copyto = copyto->next ; copyfrom = copyfrom->next ; } NewL->last = copyto ; return NewL ; } /* Print the contents of the list. */ void PrintList(list L) { node *current ; current = L->header.next ; if (current == NULL) { printf("<>\n") ; return ; } printf("<") ; while (1) { printf("\"%s\"", current->item) ; current = current->next ; if (current == NULL) break ; printf(",") ; } printf(">\n") ; } /* Free memory allocated to the list. */ void FreeList(list L) { node *current, *temp ; current = L->header.next ; while (current != NULL) { temp = current ; current = current->next ; FreeNode(temp) ; } free(L) ; } /* String in first item returned, or NULL if list is empty */ char *FirstItem(list L) { char *item ; if (L->header.next == NULL) { return NULL ; } return L->header.next->item ; } /* String in last item returned, or NULL if list is empty */ char *LastItem(list L) { return L->last->item ; } /* Returns number of items in the list */ int CountList(list L) { return L->count ; }