Previous: 4.4 Mixing Character and Numeric Input
Up: 4 Processing Character Data
Next: 4.6 Common Errors
Previous Page: 4.4 Mixing Character and Numeric Input
Next Page: 4.6 Common Errors

4.5 Menu Driven Programs

Finally, we end this chapter by using what we have learned to improve the user interface to programs: we consider the case of a program driven by a menu. In a menu driven program, the user is given a set of choices of things to do (the menu) and then is asked to select a menu item. The driver then calls an appropriate function to perform the task selected by the menu item. A switch statement seems a natural one for handling the selection from the menu.

We will modify the simple version of our payroll program to make it menu driven. While a menu is not needed in this case, we use it to illustrate the concept. The menu items are: get data, display data, modify data, calculate pay, print pay, help, and quit the program. The user selects a menu item to execute a particular path; for example, new data is read only when the user selects the menu item, get data. On demand, the current data can be displayed so the user may make any desired changes. Pay is calculated only when the user is satisfied with the data.

Figure 4.29 shows the driver for this program. (The driver of any menu driven program will look similar to this). The program prints the menu and then reads a selection character. A switch is used to select the path desired by the user. The user may type a lower or an upper case letter; both cases are included by the case labels. Usually, the driver hides the details of processing individual selections, so we have implemented most selections as function calls. The only exception here is when the selection is get data where the actual statements to read the necessary data are included in the driver itself because to use a function, it would have to read several items and somehow return them. So far we only know how to write functions that return a single value. We will address this matter in Chapter .

Notice what happens if the user elects to quit the program: a standard library function, exit(), is called. This function is like a return statement, except that it terminates the entire program rather than return from a function. It may be passed a value which is returned to the environment in which the program runs. A value of 0 usually implies normal termination of a program; any other value implies abnormal termination.

After the appropriate function is called, we terminate the selected case with a break statement to end the switch statement . The control then passes to the statement after the switch statement, namely flushing the buffer. Let us see what would happen if this flush were not present. The user selects an item by typing a character and must terminate the input with a newline. The keyboard buffer will retain all characters typed by the user, including the newline. So if the user types:

(showing the newline explicitly), the program would read the character, 'd', select the appropriate case in the switch statement and execute the path which displays data. When the break ends the switch, control returns to the while expression which reads the next character in the buffer: the newline. Since newline is not one of the listed cases, the switch will choose the default case and print an error message to the user. Thus, flushing the keyboard buffer always obtains a new selection. In fact, even if the user typed more than a single character to select a menu item (such as an entire word), the buffer will be flushed of all remaining characters after the first.

As we have mentioned before, a large program should be developed incrementally, i.e. in small steps. The overall program logic consisting of major sub-tasks is designed first without the need to know the details of how these sub-tasks will be performed. Menu driven programs are particularly well suited for incremental development. Once the driver is written, ``dummy'' functions (sometimes called stubs) can be written for each task which may do nothing but print a debug message to the screen. Then each sub-task is implemented and tested one at a time. Only after some of the basic sub-tasks are implemented and tested, should others be implemented. At any given time during program development, many sub-task functions may not yet be implemented. For example, we may first implement only get data, print data, and help ( help is easy to implement; it just prints the menu). Other sub-tasks may be delayed for later implementation. Figure 4.30 shows example implementations of the functions used in the above driver. These are in skeleton form and can be modified as needed without changing the program driver. It should be noted that the linker will require that all functions used in the driver be defined. The stubs satisfy the linker without having to write the complete function until later.

The use of a menu in this example is not very practical. It is merely for illustration of the technique. The menu is normally printed only once, so if the user forgets the menu items, he/she may ask for help, in which case the menu is printed again. Also, if the user types any erroneous character, the default case prints an appropriate message and prints the menu.



Previous: 4.4 Mixing Character and Numeric Input
Up: 4 Processing Character Data
Next: 4.6 Common Errors
Previous Page: 4.4 Mixing Character and Numeric Input
Next Page: 4.6 Common Errors

tep@wiliki.eng.hawaii.edu
Wed Aug 17 08:29:11 HST 1994