/* File: list1a.c An implementation of the list ADT using arrays */ #include #include #include "string.h" #include "list1a.h" #define START_SIZE 5 /* Private Function Prototypes */ static void CrashOnNull(void *, char *) ; static void Reallocate(list L, int inc) ; /* 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 the list bigger by at least inc elements */ static void Reallocate(list L, int inc) { node *temp ; int new_limit ; new_limit = L->limit + inc ; if (new_limit < 2 * L->limit) { /* at least double */ new_limit = 2 * L->limit ; } temp = (node *) realloc(L->array, new_limit * sizeof(node)) ; CrashOnNull(temp, "could not reallocate array") ; L->array = temp ; L->limit = new_limit ; } /* Public Functions */ /* Make a new list */ list CreateList (void) { list NewL ; node *temp ; NewL = (list) malloc(sizeof (*NewL)) ; CrashOnNull(NewL, "cannot make new list") ; temp = (node *) malloc(START_SIZE * sizeof(node)) ; CrashOnNull(temp, "cannot make new array") ; NewL->array = temp ; NewL->size = 0 ; NewL->limit = START_SIZE ; return NewL ; } /* Add item to the end of the list */ void Append(list L, char *item) { if (L->size == L->limit) Reallocate(L,1) ; /* Important: use strdup() */ L->array[L->size] = strdup(item) ; L->size++ ; } /* Add item to the beginning of the list */ void Prepend(list L, char *item) { int i ; if (L->size == L->limit) Reallocate(L,1) ; /* Copy L->array[0..size-1] to L->array[1..size] */ for (i = L->size ; i >= 1 ; i--) { L->array[i] = L->array[i-1] ; } /* Important: use strdup() */ L->array[0] = strdup(item) ; L->size++ ; } /* Does item with key appear on the list? 0=No 1=Yes */ int IsMember(list L, char *key) { int i, size ; size = L->size ; for (i = 0 ; i < size ; i++) { if (strcmp(L->array[i], key) == 0) return 1 ; } return 0 ; } /* Returns the pointer to the node that contains the given key, or NULL if no such node. Note: that this is different from the representation used in the linked list implementation, but the main program doesn't need to know this. */ node *Locate(list L, char *key) { int i, size ; size = L->size ; for (i = 0 ; i < size ; i++) { if (strcmp(L->array[i], key) == 0) return &(L->array[i]) ; } 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 *ptr, *end ; end = L->array + L->size ; /* Sanity Check */ if (position < L->array || position >= end) return ; /* Copy L->array elements from (position + 1)..end to position..(end-1). Weird use of pointer arithmetic necessary for compatibility with previous list1.h interface */ for (ptr = position ; ptr < end ; ptr++) { *ptr = *(ptr + 1) ; } L->size-- ; } /* Add list L2 to the end of list L1. L2 is destroyed. */ void Concatenate(list L1, list L2) { int size1, size2, totalsize, i ; size1 = L1->size ; size2 = L2->size ; totalsize = size1 + size2 ; if (totalsize >= L1->limit) Reallocate(L1, size2) ; L1->size = totalsize ; /* Copy elements of L2->array to end of L1->array. Note that we do not use strdup() here. */ for (i = 0 ; i < size2 ; i++) { L1->array[i+size1] = L2->array[i] ; } /* Manually free L2. Should not free elements of L2->array since they are now used by L1. */ free(L2->array) ; free(L2) ; } /* Duplicate list. All items and nodes have newly allocated memory. */ list ListDup(list L) { list NewL ; int i, size ; NewL = CreateList() ; NewL->size = size = L->size ; if (size >= NewL->limit) { Reallocate(NewL, size - NewL->limit) ; } /* Important: use strdup() */ for (i = 0 ; i < size ; i++) { NewL->array[i] = strdup(L->array[i]) ; } return NewL ; } /* Print the contents of the list. */ void PrintList(list L) { int i, size ; size = L->size ; if (size == 0) { printf("<>\n") ; return ; } i = 0 ; printf("<") ; while (1) { printf("\"%s\"", L->array[i]) ; i++ ; if (i == size) break ; printf(",") ; } printf(">\n") ; } /* Free memory allocated to the list. */ void FreeList(list L) { int i, size ; size = L->size ; for (i = 0 ; i < size ; i++) { free(L->array[i]) ; } free(L->array) ; free(L) ; } /* String in first item returned, or NULL if list is empty */ char *FirstItem(list L) { if (L->size == 0) return NULL ; return L->array[0] ; } /* String in last item returned, or NULL if list is empty */ char *LastItem(list L) { if (L->size == 0) return NULL ; return L->array[L->size - 1] ; } /* Returns number of items in the list */ int CountList(list L) { return L->size ; }