/* * File: stacktypes.h * ------------------ * This file exists solely to isolate the defintition of stackElementT * from the rest of the stack.h interface. This way the client can control * the type of elements place in the tack without editing stack.h */ typedef char stackElementT; /* ------------< end file "stacktypes.h" >------------ */ /* * File: stack.h * ------------ * This is the interface for a general stack. */ #ifndef _stack_h #define _stack_h /* * Type: stackElementT * ------------------- * This is the type of the objects pushed onto the stack. * Edit stacktypes.h to define stackElementT to be type of things to be * placed in stack. */ #include "genlib.h" /* need bool typedef */ #include "stacktypes.h" /* need stackElementT typedef */ /* * Type: stackADT * ------------- * The actual implementation of a stack is completely hidden. Client will * work with stackADT which is a pointer to underlying stackCDT */ /* note: need word struct below so that the compiler knows at least that * a stackCDT will be some sort of struct. */ typedef struct stackCDT *stackADT; /* * Function: NewStack * Usage: stack = NewStack(); * ------------------------- * A new empty stack is allocated, created and returned. */ stackADT NewStack(void); /* Function: FreeStack * Usage: FreeStack(stack); * ----------------------- * This function frees all memory associated with the stack. stack * may not be used again unless NewStack(stack) is called first. */ void FreeStack(stackADT stack); /* * Functions: Push, Pop * Usage: Push(stack, element); element = Pop(stack); * -------------------------------------------- * These are the fundamental stack operations which push elements onto and * pop elements off of the stack. A call to Pop on an empty stack or to * Push on a full stack is an error. Make use of StackIsFull() and * StackIsEmpty() (see below) to avoid these errors. */ void Push(stackADT stack, stackElementT element); stackElementT Pop(stackADT stack); /* * Functions: StackIsEmpty, StackIsFull * Usage: if (StackIsEmpty(stack)) ... * ----------------------------------- * These return TRUE if the stack is respectively empty or full. */ bool StackIsEmpty(stackADT stack); bool StackIsFull(stackADT stack); /* * Function: StackDepth * Usage: n = StackDepth(stack); * ----------------------------- * This returns the number of elements currently on the stack. */ int StackDepth(stackADT stack); #endif /* ------------< end-of-file "stack.h" >------------ */ /* * File: stack.c (version 1) * ------------- * This is an array-based implementation of a stack. */ #include #include #include "stack.h" /* * Constants * --------- * MAX_STACK_SIZE = largest number of items stack can hold * ERROR_ these are for returning error conditions from main */ #define MAX_STACK_SIZE 100 #define ERROR_STACK 2 #define ERROR_MEMORY 3 struct stackCDT{ stackElementT array[MAX_STACK_SIZE]; int count; }; stackADT NewStack(void) { stackADT stack; stack = malloc(sizeof (stack)); if ( stack == NULL ) { fprintf(stderr,"Insufficient Memory to Allocate new Stack"); exit(ERROR_MEMORY); } stack->count = 0; return (stack); } void FreeStack(stackADT stack) { free (stack); } void Push(stackADT stack, stackElementT element) { if (stack->count >= MAX_STACK_SIZE) { fprintf(stderr, "Stack Overflow."); exit(ERROR_STACK); } stack->array[stack->count++] = element; } stackElementT Pop(stackADT stack) { if (stack->count < 1) { fprintf(stderr,"Pop to Empty Stack"); exit(ERROR_STACK); } return (stack->array[--stack->count]); } bool StackIsEmpty(stackADT stack) { return (stack->count < 1); } bool StackIsFull(stackADT stack) { return (stack->count >= MAX_STACK_SIZE); } int StackDepth(stackADT stack) { return (stack->count); } /* ---------- end of file stack.c --------- */ /* * File: stack.c (version 2) * ------------- * This is an array-based implementation of a stack which uses * dynamic allocation to make a larger array if the array gets full. */ #include #include #include "genlib.h" #include "stack.h" #define INIT_STACK_SIZE 20 /* number of elements stack can hold * before reallocation */ struct stackCDT{ stackElementT *array; int count; int size; }; /* * Function: ExpandStack * Usage: ExpandStack(stack); * -------------------------- * This function attempts to increase the allocated size for stack->array and * returns TRUE if this was successful, FALSE otherwise. * It is NOT exported thru the interface. */ static bool ExpandStack(stackADT stack); stackADT NewStack(void) { stackADT stack; stack = GetBlock(sizeof (struct stackCDT)); stack->array = GetBlock( INIT_STACK_SIZE * sizeof (stackElementT) ); stack->count = 0; stack->size = INIT_STACK_SIZE; return (stack); } void FreeStack(stackADT stack) { free(stack->array); free(stack); } void Push(stackADT stack, stackElementT element) { if (stack->count == stack->size) { ExpandStack(stack); } stack->array[stack->count++] = element; } stackElementT Pop(stackADT stack) { if (stack->count < 1) {Error("Pop to Empty Stack");} return (stack->array[--stack->count]); } bool StackIsEmpty(stackADT stack) { return (stack->count < 1); } bool StackIsFull(stackADT stack) { /* note: this could have been done in one line, namely: * * return ( ! ((stack->count < stack->size) || ExpandStack(stack)) ); * * but this version makes it clearer what is going on. */ /* also note: ExpandStack(stack) is only called if * stack->count >= stack.size */ bool stackHasRoom; stackHasRoom = (stack->count < stack->size) || ExpandStack(stack) ; return ( ! stackHasRoom ); } int StackDepth(stackADT stack) { return (stack->count); } /* * Function: ExpandStack * --------------------- * return value of ExpandStack tells whether the expansion was possible. * * Algorithm Outline: * 1) allocate memory for new larger "array" * 2) copy stack elements from old array to new * 3) deallocate old array * 4) connect new array to the stack struct: stack->array = newArray */ static bool ExpandStack(stackADT stack) { stackElementT *newArray; int i, newSize; newSize = stack->size * 2; newArray = malloc(newSize * sizeof(newArray)); if (newArray == NULL) { return FALSE; /* unable to allocate space for larger array */ } for (i = 0; i < stack->count; i++) { newArray[i] = stack->array[i]; } free(stack->array); stack->array = newArray; stack->size = newSize; /* note: stack->count remains unchanged */ return TRUE; } /* ---------- end of file stack.c --------- */