Principle 6.7.1. EFFECTIVE DESIGN: Modularity.
Encapsulating code in a method is a good way to avoid redundancy in a program.
KeyboardReader
class. To signify the end of the list, we will use a sentinel value—9999 or \(-1\) or some other value that won’t be confused with a legitimate grade. Because we do not know exactly how many grades will be entered, we will use a noncounting loop in this algorithm. Because there could be no grades to average, we will use a while
structure so it is possible to skip the loop entirely in the case that there are no grades to average.initialize runningTotal to 0 // Initialize
initialize count to 0
prompt and read the first grade // Priming read
while the grade entered is not 9999 {// Sentinel test
add it to the runningTotal
add 1 to the count
prompt and read the next grade // Update}
if (count > 0) // Guard against divide by 0
divide runningTotal by count
output the average as the result
grade
, is read before the loop test is made. This is known as a priming read. It is necessary in this case, because the loop test depends on the value that is read. Within the loop’s body, the updater reads the next value for grade. This is a standard convention for coding while
structures that involve input, as this problem does. Note also that we must make sure that count
is not 0 before we attempt to compute the average because dividing by 0 would cause a divide-by-zero error.double
variable named grade
. The loop will terminate when grade
equals 9999, so its entry condition will be (grade != 9999)
. Because this condition uses grade
, it is crucial that the grade
variable be initialized before the bound test is made. This requires a priming read. By reading the first value of grade
before the loop entry condition is tested, ensures that the loop will be skipped if the user happens to enter the sentinel (9999) on the very first prompt. In addition to reading the first exam score, we must initialize the variables used for the running total and the counter. Thus, for our initialization step, we get the following code:double runningTotal = 0;
int count = 0;
reader.prompt("Input a grade (e.g., 85.3) " +
"or 9999 to indicate the end of the list >> ");
double grade =
reader.getKeyboardDouble(); // Priming input
while (grade != 9999) { // Loop test: sentinel
runningTotal += grade;
count++;
reader.prompt("Input a grade (e.g., 85.3) " +
"or 9999 to indicate the end of the list >> ");
grade = reader.getKeyboardDouble(); // Update:input
} // while
grade
variable. A better design would be to encapsulate these into a method and then call the method both before and within the loop. The method should take care of prompting the user, reading the input, converting it to double
, and returning the input value. The method doesn’t require a parameter:private double promptAndRead() {
reader.prompt("Input a grade (e.g., 85.3) " +
"or 9999 to indicate the end of the list >> ");
double grade = reader.getKeyboardDouble();
// Confirm input
System.out.println("You input " + grade + "\n");
return grade;
}
private
method. It will be used to help us perform our task but won’t be available to other objects. Such private methods are frequently called helper methods.promptAndRead()
method.public double inputAndAverageGrades() {
double runningTotal = 0;
int count = 0;
double grade = promptAndRead();// Priming initializer
while (grade != 9999) { // Loop test: sentinel
runningTotal += grade;
count++;
grade = promptAndRead();// Update: get next grade
} // while
if (count > 0) // Guard against divide-by-zero
return runningTotal / count;// Return the average
else
return 0; // Special (error) return value
}
public
method. This will be the method you call to calculate your course average.Average.java
application is shown in Listing 6.7.3 or at Average on repl. Try it below.