Got it! This site uses cookies. You consent to this by clicking on "Got it!" or by continuing to use this website.nbsp; Note: This appears on each machine/browser from which this site is accessed.
This page introduces the concept of a stack and then uses abstraction to turn the mental model of a stack into an ADT (Abstract Data Type) and then to a separate module.
2. Abstract data types
Some common abstract data types include the following.
A stack is a first-in last-out data structure
A queue is a first-in first-out data structure
Here we look at stacks.
3. Stacks
A stack is an ADT used to push items on the stack and pop items off the stack. It as called first-in last-out as only the top item on the stack is available (through normal channels or calls).
Stacks are often used to remember where you were, start something new, then return and pick up where you left off.
4. Stack operations
The following are stack operations.
Init to initialize the stack to empty
Push to push an item onto the stack
Pop to pop an item off of the stack
Top to get the top item on the stack (without changing the stack)
Empty to determine if the stack is empty
5. Error checking
In production programs, some form of error checking is often done.
This error checking can be for each and every stack access.
Or, it can be the responsibility of the calling program (for abstracted stack routines).
Or, a correctness proof make it impossible for an error to happen (e.g., for advanced programming language design concepts).
And so on.
6. Implementation
A stack can be implemented as a list. The list can be implemented as an array.
Here is an implementation and test program for a stack for items of type integer. To keep the example simple, no error checking is done.
7. Stack data structures
Here are the data structures for the stack.
8. Stack initialization
The stack is initialized as follows.
9. Trailer loop
The input uses a trailer loop to get values and push them on the stack.
10. Stack output
The output pops values off of the stack and prints them, which means that they are printed in reverse order of how they were read from the input.
11. Complete program
Here is the C code.
12. Examples of input and output
Here are some examples of input and output for the above program code.
Here is an example input.
For the above example input, here is the expected output.
13. Abstraction
The mental model of a stack as implemented above can be abstracted to use functions to more separate the mental model of a stack from the implementation of that model.
In doing the abstraction, the code in the local scope of main is moved to the global scope.
14. Data structures
Here are the data structures.
15. Const and define
Note: The const has been used at the local scope. Due to programming tradition, the define is usually used at the global scope.
16. Names
Note: The STACKMAX name could be used at the local scope level using const.
But that name is used elsewhere in C, so, in this case, STACKMAX1 is used at the global scope level.
17. Initialize the stack
The stack is initialized by setting stackLen1 to 0 (zero).
18. Stack push
The function stackPush pushes the supplied value onto the stack.
19. Stack pop
The function stackPop pops the top of the stack off the stack and returns that value.
20. Stack empty
The function stackEmpty returns 0 if the stack is empty. Otherwise, the length of the stack is returned, a feature of this routine.
21. Stack top
The stackTop function returns the value at the top of the stack.
Here is the C code.
22. Examples of input and output
Here are some examples of input and output for the above program code.
Here is an example input.
For the above example input, here is the expected output.
23. Module migration
This code for implementing a stack might be useful in other programs so that the code can be reused.
There are many sophisticated ways to do this. A simple and common way to get started is now covered.
The first step is to separate the interface from the implementation.
24. Interface and implementation
The implementation contains the actual code that does the computations.
The interface is a controlled way in which to access the implementation.
Below is the above code separated into interface and implementation parts.
25. Interface
The interface consists of constants, variables, and functions. The interface for the stack implementation is as follows.
26. Interface notes
Note the function headers following by a semicolon. These must match exactly the implementation which is moved below the main function.
27. Prototypes
A function header (without the implementation body) is sometimes called a prototype although this word can be confused with the object-oriented feature of a prototype.
28. Signature
The generic term for a function header is a signature though a signature can be a more general concept.
The formal parameter names of the interface do not need to match the formal parameter names of the implementation, though this is usually done.
Here is the C code.
29. Examples of input and output
Here are some examples of input and output for the above program code.
Here is an example input.
For the above example input, here is the expected output.
30. Encapsulation
The implementation encapsulates the functionality.
The code in main can no longer access the internals of the stack.
The code in main must only access the stack through the interface.
This concept is called encapsulation.
31. Modules
The next step is to abstract the interface and implementation to a module.
A module is a collection of code that can be reused between programs.
32. C modules
In C, a module is created as follows. Other languages have other conventions for how this is done but follow the same general ideas.
0. Separate the interface and implementation parts, as in the above code.
1. A name for the module is decided, such as rsStack. The "rs" may be the programmer's initials. Or the company initials. Or some prefix that makes it unlikely that the same module would be named the same name by someone else.
2. The interface is put into file rsStack.h (The letter h is for "header").
3. The implementation is put into file rsStack.c (The letter c is for code in the C programming language).
4. The following directive is added to the top of the main program.
#include "rsStack.h"
Note that (user defined) non-standard modules use double quotes while standard modules use angle brackets such as the following.
#include <stdio.h>
This is just a convention as either will work for either purpose.
33. Program using the module
The following program now results. Note how much smaller it is since functionality has been moved to a module.
One disadvantage is that one must now know what that interface is, how to use it, and code is now separated between many files instead of in just one program file.
Here is the C code.
34. Examples of input and output
Here are some examples of input and output for the above program code.
Here is an example input.
For the above example input, here is the expected output.
35. Interface
Here is the interface in the header file rsStack.h
36. Implementation
Here is the implementation in the code file rsStack.c
37. Functions: message passing
Function calls can be thought of as a message passing system.
The main routine passes values to the function
The function receives values, computes values, and returns a value.
The main routine receives the value from the function and uses it.
38. How function call and returns are done
In case you wanted to know: This is (one way, simplified as to) how the main routines interacts with a function.
The main routine calculates values for all passed parameters. These parameters are pushed on the run-time variable stack.
The function retrieves the needed values off of the stack.
On return, the function pops the passed values off of the stack and then pushes the return value on the stack.
The main function pops the return value off of the stack.