5.10. Sentinel-Controlled RepetitionLet us generalize Section 5.9's class-average problem.
In the previous class-average example, the problem statement specified the number of students, so the number of grades (10) was known in advance. In this example, no indication is given of how many grades are to be input. The program must process an arbitrary number of grades. How can it determine when to stop the input of grades? How will it know when to calculate and print the class average? One way to solve this problem is to use a special value called a sentinel value (also called a signal value, a dummy value or a flag value) to indicate "end of data entry." The user enters grades until all legitimate grades have been entered. The user then types the sentinel value to indicate that no more grades will be entered. Sentinel-controlled repetition is called indefinite repetition because the number of repetitions is not known before the loop begins its execution. It is crucial to employ a sentinel value that cannot be confused with an acceptable input value. Grades on a quiz are nonnegative integers, so 1 is an acceptable sentinel value for this problem. A run of the class-average program might process a stream of inputs such as 95, 96, 75, 74, 89 and 1. The program would then compute and print the class average for the grades 95, 96, 75, 74 and 89. The sentinel value, 1, should not enter into the averaging calculation. Common Programming Error 5.4
Implementing Sentinel-Controlled Repetition in Class GradeBookFigure 5.12 shows the Visual Basic class GradeBook containing the method DetermineClassAverage that solves the class average problem with sentinel-controlled repetition. Although each grade is an integer, the averaging calculation is likely to produce a number with a decimal pointa real number or floating-point number. The type Integer cannot represent such a number, so this class uses type Double to do so. Figure 5.12. Sentinel-controlled repetition: Class-average problem.
In this example, we see that control statements may be stacked on top of one another (i.e., placed in sequence). The While statement (lines 6067) is followed in sequence by an If...Then...Else statement (lines 7080). Much of the code in this program is identical to the code in Fig. 5.10, so we concentrate on the new features and issues. Line 48 declares Double variable average. This variable allows us to store the calculated class average as a floating-point number. We discuss floating-point numbers in more detail shortly. Line 52 initializes gradeCounter to 0, because no grades have been entered yet. Remember that this program uses sentinel-controlled repetition to input the grades from the user. To keep an accurate record of the number of grades entered, the program increments gradeCounter only when the user inputs a valid grade value. Recall that Integer variables are initialized to zero by default, so lines 5152 can be omitted. Program Logic for Sentinel-Controlled Repetition vs. Counter-Controlled RepetitionCompare the program logic for sentinel-controlled repetition in this application with that for counter-controlled repetition in Fig. 5.10. In counter-controlled repetition, each iteration (repetition) of the While statement (e.g., lines 5561 of Fig. 5.10) reads a value from the user for the specified number of iterations. In sentinel-controlled repetition, the program reads the first value (lines 5657 of Fig. 5.12) before reaching the While. This value determines whether the program's flow of control should enter the body of the While. If the condition of the While is false, the user entered the sentinel value, so the body of the While does not execute (i.e., no grades were entered). If, on the other hand, the condition is true, the body begins execution, and the loop adds the grade value to the total (line 61). Lines 6566 in the loop's body input the next value from the user. Next, program control reaches the end of the While statement, so execution continues with the test of the While's condition (line 60). The condition uses the most recent grade input by the user to determine whether the loop's body should execute again. Note that the value of variable grade is always input from the user immediately before the program tests the While condition. This allows the program to determine whether the value just input is the sentinel value before processing that value (i.e., adding it to the total). If the sentinel value is input, the loop terminates, and the program does not add 1 to the total. Good Programming Practice 5.2
After the loop terminates, the If...Then...Else statement at lines 7080 executes. The condition at line 70 determines whether any grades were input. If none were input, the Else part (lines 7879) of the If...Then...Else statement executes and displays the message "No grades were entered" and the method returns control to the calling method. Floating-Point Numbers and Type DoubleAlthough each grade entered is an integer, the averaging calculation is likely to produce a number with a decimal point (i.e., a floating-point number). The type Integer cannot represent floating-point numbers, so this program uses data type Double to store floating-point numbers. Visual Basic provides two primitive types for storing floating-point numbers in memorySingle and Double. The primary difference between them is that Double variables can store numbers of larger magnitude and finer detail (i.e., more digits to the right of the decimal pointalso known as the number's precision) than Single variables. Floating-Point Number Precision and Memory RequirementsVariables of type Single represent single-precision floating-point numbers and have seven significant digits. Variables of type Double represent double-precision floating-point numbers. These require twice as much memory as Single variables and provide 15 significant digitsapproximately double the precision of Single variables. For the range of values required by most programs, variables of type Single should suffice, but you can use Double to play it safe. In some applications, even variables of type Double will be inadequatesuch applications are beyond the scope of this book. Most programmers represent floating-point numbers with type Double. In fact, Visual Basic treats all the floating-point numbers you type in a program's source code (such as 7.33 and 0.0975) as Double values by default. Such values in the source code are known as floating-point literals. See Section 7.11 for the ranges of values for Singles and Doubles. Implicitly Converting Between Primitive TypesIf at least one grade was entered, line 72 of Fig. 5.12 calculates the average of the grades. Recall from Fig. 5.10 that we used the integer division operator to yield an integer result. Since we are now calculating a floating-point value, we use the floating-point division operator. But the operands of the division in line 72 are of type Integer. To perform a floating-point calculation with integer values, we must temporarily treat these values as floating-point numbers for use in the calculation. The floating-point division operator is defined to operate on values of three typesSingle, Double and Decimal (you will learn about type Decimal in Chapter 6). To ensure that the operator's operands are one of these three types, Visual Basic performs an operation called implicit conversion on selected operands. For example, in an expression using the floating-point division operator, if both operands are of type Integer, the operands will be promoted to Double values for use in the expression. In this example, the values of total and gradeCounter are promoted to type Double, then the floating-point division is performed and the result of the calculation is assigned to average. We'll say more about the implicit conversion rules in Section 7.9. Formatting for Floating-Point NumbersLine 77 outputs the class average. In this example, we decided to display the class average rounded to the nearest hundredth and to output the average with exactly two digits to the right of the decimal point. Note that the call to method WriteLine in line 77 uses the string "{0:F}" to indicate that the value of average should be displayed in the command prompt as a fixed-point number, (i.e., a number with a specified number of places after the decimal point). The numeric value that appears before the colon (in this case, 0) indicates which of WriteLine's arguments will be formatted0 specifies the first argument that occurs after the string is passed to WriteLine, namely average. Additional values can be inserted into the string to specify other arguments. If we had passed total as a third argument to method WriteLine and used the string "{1:F}" the value to be formatted would be total. The value after the colon (in this case, F) is known as a format specifier, which indicates how a value is to be formatted. The format specifier F indicates that a fixed-point number should (by default) be displayed with two decimal places. This can be changed by placing a numeric value after the format specifier. For example, the string "{0:F3}" would display a fixed-point value with three decimal places. Some of the more common format specifiers are summarized in Fig. 5.13. The format specifiers are case insensitive. Also, the format specifiers D and X can be used only with integer values.
Good Programming Practice 5.3
The three grades entered during the sample execution of module GradeBookTest (Fig. 5.14) total 257, which yields the average 85.666666.... The format specifier causes the output to be rounded to the specified number of digits. In this program, the average is rounded to the hundredths position and is displayed as 85.67. Figure 5.14. GradeBookTest module creates an object of class GradeBook (Fig. 5.12) and invokes its DetermineClassAverage method.
|