Developing a non-trivial program can be a major undertaking. To make the work as painless as possible, it is best to have a method of attack. There are two techniques which are commonly used: bottom-up and top-down.
Both require pre-planning. This is best done by creating pseudocode.
Typically, when a problem is posed, you will have an idea of what the output should be like. From there you determine what sort of information is required to develop the output. Then you can fill in the middle of your algorithm -- how to process the input so you can produce the output.
Alternatively, you can brainstorm the kinds of tasks that will be required, making a list as they come to mind. These can then be organized into a coherent algorithm, thus producing the requisite pseudocode.
Once the pseudocode has been written, it will be much easier to write the individual functions to perform the required tasks.
For the purposes of this discussion, let us consider the overworked area-of-a-triangle program. Here is simple pseudocode:
We will be developing the program discussed in Functions II. There you will find a complete presentation of the parameters used.
To begin, we will write a simple program which does absolutely nothing but call a set of function stubs in sequence. These stubs currently perform no useful purpose other than to serve as placeholders for the individual steps in the algorithm. Each of the functions matches up with one of the steps in the pseudocode.
Although this initial program generates no output, it should be noted that a considerable amount of preplanning has already occurred, parameters having been selected for three of the functions.
#include <stdio.h> /* standard I/O header file */
/* function prototypes */
void Introduction();
void InputtingData(int *, int *);
void Calculation(int, int, float *);
void PrintingResults(int, int, float);
void main()
{
int base;
int height;
float Area;
Introduction();
InputtingData(&base, &height);
Calculation(base, height, &Area);
PrintingResults(base, height, Area);
}
void Introduction()
{
} /* Introduction */
void InputtingData(int *b, int *h)
{
} /* InputtingData */
void Calculation(int b, int h, float *A)
{
} /* Calculation */
void PrintingResults(int b, int h, float A)
{
} /* PrintingResults */
We can now start writing the code to make the functions actually do their tasks. Since Introduction() is not directly involved in the inputting, processing and outputting of the data, it can be written at any time. If you are new to programming, you may want to fill it in right away so that you have a constant reminder about what the final program is supposed to do.
There are also deadline considerations. If you get the main algorithm working with time to spare, you can spend the remaining time fancying up the introduction and user interface; on the other hand, if you spend too much time perfecting the introduction, you could run out of time before you finish the main task.
We will look briefly at two techniques for proceeding with the programming solution.
For beginning programmers, it may be wise to ascertain that we have indeed chosen the right kind of parameters for the functions. The easiest way do this is to hardset the parameters inside the particular function where variables local to main() are to receive their values. (If parameters which are merely values are to be tested, the variables in the main line should be hardset before the function is called.) The following is an example using InputtingData(). If the parameters are not specified as pointers, the variables in the calling function will remain unaffected.
void InputtingData(int *b, int *h)
{
*b = 5;
*h = 7;
} /* InputtingData */
There are two easy ways to make sure that the values have made it out of the function.
In main(), print out the values of the corresponding variables after execution has returned from InputtingData().
void main()
{
Introduction();
InputtingData(&base, &height);
printf("base = %d\n", base);
printf("height = %d\n", height);
Calculation(base, height, &Area);
PrintingResults(base, height, Area);
}
Use the display feature of the gdb debugger to determine the values of base and height after execution returns to the main line from InputtingData(). This can be done by setting a breakpoint.
These methods have conflicting disadvantages: the former requires that you alter the program by adding lines which will have to be eliminated later; the latter requires that you use the display command and a breakpoint which may only be needed once. If you do not have a debugger (which is sometimes the case with other programming languages), writing values to the screen or a disk file may be the most efficient way, and sometimes the only way, to develop a program.
A second technique, for (slightly) more advanced programmers, is to continue the development process by initially filling in the function(s) which handle input, then the ones which process the data, and finally those which output the results. This order of doing things is very intuitive, because it typically follows the design of the algorithm as set out in the pseudocode. Assuming that the Introduction() function has already been written and tested, let us look at InputtingData() and the main line.
void main()
{
int base;
int height;
float Area;
Introduction();
InputtingData(&base, &height);
printf("base = %d\n", base);
printf("height = %d\n", height);
Calculation(base, height, &Area);
PrintingResults(base, height, Area);
}
void InputtingData(int *b, int *h)
{
printf("What is the length of the triangle's base? ");
scanf("%d", b);
printf("What is the triangle's height? ");
scanf("%d", h);
} /* InputtingData */
The printing of the values of the variables base and height allows us to see the results of the function.
While each of the succeeding functions can be written one at a time and the expanded program tested, this may not be the most efficient method. It is often better to turn a function back into a stub once it has been perfected, and to hardset the variables which were affected just after its call in the main line. This can spare you from a lot of repetitive typing while developing the rest of the program. For example, the following main line could be used to test the Calculation() function.
void main()
{
int base;
int height;
float Area;
Introduction();
InputtingData(&base, &height);
base = 5;
height = 7;
Calculation(base, height, &Area);
printf("base = %d\n", base);
printf("height = %d\n", height);
printf("Area = %.1f\n", Area);
PrintingResults(base, height, Area);
}
The techniques discussed above are not used to the exclusion of others. In fact, the method outlined on the Bottom-Up page is frequently utilized to develop individual functions which are then substituted for their corresponding stubs. This combined approach is especially important when a group of programmers is working on a single project.
© 2001 DFStermole
Created: 30 Nov 01
Last modified: 3 Dec 01