CS 117, Spring 1997

Assignment 3: Stacks

due 8:30AM Friday 4/18/97

You may work with a partner for this assignment. No groups of three or more, please.

Kruse's stack interface

On pages 81-83 of your textbook, the authors present specifications for nine fundamental stack operations. These specifications are very nicely designed, and include (as specifications should, though often don't) clear articulations of the preconditions and postconditions of the functions in question.

I have one complaint about these specifications and the implementations on pages 83-87. The preconditions for all but the CreateStack function require that "the stack exists and it has been initialized." That's good, but in practice, programmers are prone to ignoring this sort of requirement. I would like the specifications to include error-reporting, and the implementations to protect themselves against dereferencing null pointers. (The implementations in the book do in fact protect against and report errors, but I prefer moving the responsibility of how to respond to errors into the caller rather than leaving that decision up to the stack library.)

Unfortunately, it's hard to design an elegant interface that includes easy-to-use error reporting as well as natural return values. The easiest way to report errors is to have each function return a boolean value that is true if there were no errors, and false otherwise. Unfortunately, this means that functions like StackSize and StackEmpty, which have natural uses for the return value already, can't report errors in the same way as the other functions.

I propose the following solution for this particular set of specifications. For the info-reporting functions StackEmpty, StackFull, and StackSize, we'll return default values if there is an error (false for StackFull and StackEmpty, and 0 for StackSize). For all of the other functions, whose specifications in the textbook are void-valued, we'll return true or false, depending on whether an error occurred.

The errors your implementations need to guard against are (1) the parameter s is NULL for any of the functions, (2) Push is called when the stack is full, (3) Pop is called when the stack is empty, and (4) malloc returns a null pointer (in a linked implementation).

The modified specification


typedef    int    boolean;
 /* Your routines should work for any choice of
    definition of StackEntry, but please use char
	to simplify the grader's job. */

typedef    char   StackEntry; 

boolean CreateStack( Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack.
   postcondition:  Returns true if s is non-NULL and
      creation succeeded, false otherwise.  If s is
	  non-NULL, the stack has been initialized to be empty.  */
	
boolean StackEmpty( Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition: Returns true if s is non-NULL and the
      stack is empty, false otherwise. */
	
boolean StackFull( Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition: Returns true if s is non-NULL and the
      stack is full, false otherwise. */
	
boolean Push( StackEntry item, Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition:   Returns true if s is non-NULL, the
      stack was not full before the Push, and the Push
	  succeeded, false otherwise.  If return value is true
	  (that is, the Push succeeded), the item has been
	  stored at the top of the stack. */
	
boolean Pop( StackEntry *item, Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition:   Returns true if s is non-NULL, the
      stack was not empty before the Pop, and the Pop
	  succeeds, false otherwise.  If return value is true
	  (that is, the Pop succeeded), the top element of
	  the stack has been removed and stored in *item. */
	
boolean ClearStack( Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition:   Returns true if s is non-NULL and
      the deletion of previous contents succeeded, false
	  otherwise.  If return value is true (that is, the
	  ClearStack succeeded), all entries in the stack have
	  been deleted, and the stack is now empty. */

int StackSize( Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition:   Returns the number of elements in the
      stack if s is non-NULL, 0 otherwise. */

boolean StackTop( StackEntry *item, Stack *s );
/* precondition: The Stack pointer s is NULL or points
      to a variable of type Stack for which CreateStack
	  has been called.
   postcondition:   Returns true if s is non-NULL and the
      stack was not empty before the call to StackTop,
	  false otherwise.  If return value is true, the
	  stack is unchanged, but a copy of its top element
	  is stored in *item. */

boolean TraverseStack( Stack *s, void (*Visit)() );
/* DON'T DO THIS ONE.  Instead, you might want to write
   yourself a void PrintStack( Stack *s ) for debugging
   purposes. */

Your job

Write and test two implementations of the first eight functions out of the nine-function stack specification, with the void-valued functions replaced by boolean-valued functions and the non-void functions returning default values in case of errors as above. (Don't write TraverseStack. We'll talk about traversals when we look at trees.)

To help out the grader, please define StackEntry as a char.

Your first implementation, using an array, is almost done already on pages 83-85.

The second implementation is begun on pages 85-87.

Hand in two source files (stackarray.c and stacklinked.c) and their corresponding headers. Do not hand in a main program.

When you test your implementations, a single main program should work for both implementations. All you should need to change in main.c to test the second implementation instead of the first is change #include "stackarray.h" to #include "stacklinked.h".

Questions? Talk to me.

Start early, keep in touch, and have fun.



Jeff Ondich, Department of Mathematics and Computer Science, Carleton College, Northfield, MN 55057, (507) 646-4364, jondich@carleton.edu