Previous: A Simple Loop --- while
Up: 2.5 More C Statements
Next: 2.5.6 More Complex Loop Constructs - Nested Loops
Previous Page: A Simple Loop --- while
The program in the last section illustrates one way to control how many times a loop is executed, namely counting the iterations. Rather than build the number of iterations into the program as a constant, pay3.c requires the user to type in the number of people for whom pay is to be computed. That technique may be sufficient sometimes, but the user may not be happy if each time a program is used, one has to count tens or hundreds of items. It might be more helpful to let the user signal the end of data input by typing a special value for the data. For example, the user can be asked to type a zero for the id number of the employee to signal the end of data (as long as zero is not an otherwise valid id number). This suggests another refinement to our task:
PAY4: Same as PAY3, except that pay is to be calculated for any number of people. In addition, we wish to keep a count of the number of people, calculate the gross total of all pay disbursed, and compute the average pay. The end of data is signaled by a negative or a zero id number.
Logic for the while loop is quite simple. The loop repeats as long as id_number is greater than 0. This will also require us to initialize the id_number to some value before the loop starts and to update it within the loop body to ensure loop termination. For our task, we must also keep track of the number of people and the gross pay. After the while loop, we must calculate the average pay by dividing gross pay by the number of people. Here is the algorithm logic using the while loop construct.
set gross pay and number of people to zero
prompt user and read the first id number
while (id number > 0) {
read remaining data, compute pay, print data
update number of people
update gross pay
prompt user and read next id number
}
set average pay to (gross pay / number of people)
Values of gross pay and number of people must be kept as cumulative values,
i.e. each time pay for a new person is computed, the number of people must be
increased by one, and gross pay must be increased by the pay for that person.
Cumulative sum variables must be initialized to zero before the loop,
similar to our counting variable in the last example;
otherwise those variables will contain garbage values which will then be
increased each time the loop is processed.
Our algorithm is already ``code like'', and its implementation
should be straightforward, but first let us consider the debugging
process for the program.
As programs get more complex, manual program tracing becomes tedious; so let's let the program itself generate the trace for us. During program development, we can introduce printf() statements in the program to trace the values of key variables during program execution. If there are any bugs in program logic, the program trace will alert us. Such printf() statements facilitating the debug process are called debug statements. Once the program is debugged, the debug statements can be removed so that only relevant data is output. In our example, we will introduce debug statements to print values of gross pay and number of people.
In the program, we should not only prompt the user to type in an ID number but should also inform him/her that typing zero will terminate the data input. (Always assume that users do not know how to use a program). Prompts should be clear and helpful so a user can use a program without any special knowledge about the program. Figure 2.13 shows the program that implements the above algorithm.

Much of the code is similar to our previous program. We have introduced two additional variables, number, an integer counting the number of employees processed, and gross, a float to hold the cumulative sum of gross pay. Before the while loop, these variables are initialized to zero; otherwise only garbage values will be updated. Each time the loop body is executed, these values are updated: number by one, and gross by the new value of total_pay.
A debug statement in the while loop prints the updated values of gross and number each time the loop is executed. The output will begin with the word debug just to inform us that this is a debug line and will be removed in the final version of the program. Enough information should be given in debug lines to identify what is being printed. (A debug print out of line after line of only numbers isn't very useful for debugging). The values can alert us to possible bugs and to probable causes. For example, if we did not initialize gross to zero before the loop, the first iteration will print a garbage value for gross. It would instantly indicate to us that gross is probably not initialized to zero. We have also not indented the debug printf() statement to make it stand out in the source code.
Once the while loop terminates, the average pay must be computed as a ratio of gross and number. We have added another declaration at the beginning of the block for average and the appropriate assignment statement to compute the average at the end. Note we have used the cast operator to cast number to a float for the division. This is not strictly necessary; the compiler will do this automatically; however, it is good practice to cast operands to like type in expressions so that we are aware of the conversion being done.
It is possible that no data was entered at all, i.e. the user enters 0 as the first id, in which case number is zero. If we try to divide gross by number, we will have a ``divide by zero'' run time error. Therefore, we check that number is greater than zero and only calculate the average and print the result when employee data has been entered.
With all of these changes made as shown in Figure 2.13, the program is compiled, and run resulting in the following sample session:
The debug lines show the changes in gross and number each time the loop is executed. The first such line shows the value of gross the same as that of the total pay and the value of number as 1. The next pass through the loop shows the variables are updated properly. The program appears to be working properly; nevertheless, it should be thoroughly tested with a variety of data input. Once the program is deemed satisfactory, the debug statements should be removed from the source code and the program recompiled.