CS 1063 Intro. to Programming
|
In the examples below, various deliberate errors are made initially to illustrate the process of programming.
The examples are shown just as simple loops inside a main function, but at the end the task of the loop is reformulated to take the form of a object-oriented example.
Consider the following problem statement:
You are to write a Java program that will read integer exam scores one at a time until a -1 signals the end of the input. The first try at a program is the following (which uses the Java 1.5 version of user input).
NOTE: INCORRECT PROGRAM
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score;
int sum = 0;
int count = 0;
double average;
while (score != -1) {
score = in.nextInt();
count++;
sum = sum + score;
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
When the program is run with the given input, the result is:
90 100 80 -1 count: 4, sum: 269 average: 67.25
NOTE: FLAWED PROGRAM (flaws partly marked in red)
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score = 0;
int sum = 1;
int count = -1;
double average;
while (score != -1) {
score = in.nextInt();
count++;
sum = sum + score;
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
Here is the new run of this program:
90 100 80 -1 count: 3, sum: 270 average: 90.0
The next day our supervisor says that users are entering various negative numbers to terminate the input, rather than just -1, and they are getting the wrong answers. We try to insist that the users be made to use just -1, but eventually we agree to rewrite the program so that any negative number will terminate the input. Eventually, we decide to alter the final value of score so that the answer will be correct. Just after the while loop, we add the statement:
which should compensate for the extra negative score added in. When we compile and run this, the result is even further off, so we try:
We also waste a run till we realize that the while condition needs to be while (score >= 0). The final version of the program now looks like:
NOTE: TERRIBLY FLAWED PROGRAM (flaws partly marked in red)
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score = 0;
int sum = 1;
int count = -1;
double average;
while (score >= 0) {
score = in.nextInt();
count++;
sum = sum + score;
}
sum = sum - score - 1;
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
Here is the new run of this program:
90 100 80 -47 count: 3, sum: 270 average: 90.0
Notice that in the statement sum = sum - score - 1;, the final - 1 is only there because of the earlier patch to initialize sum to 1. If another programmer working with this code were to discover the "mistake" of initializing sum to 1, and put in a change to initialize it to 0, this "correction" would introduce a new bug because of the strange patch of subtracting an extra 1 from sum at the end.
FIRST GOOD VERSION OF PROGRAM (Uses priming read. Changes partly commented in dark red.)
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score;
int sum = 0;
int count = 0;
double average;
// use a "priming" read just before the loop
score = in.nextInt();
while (score >= 0) { // this will terminate loop when negative number read
count++;
sum = sum + score;
score = in.nextInt(); // read again just before repeating the loop
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score;
int sum = 0;
int count = 0;
double average;
while(true) { // infinte loop, must terminate inside
score = in.nextInt();
// terminate loop right after reading the negative score
// without counting the negative number as a score or adding it in
if (score < 0) break;
count++;
sum = sum + score;
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int score;
int sum = 0;
int count = 0;
double average;
// use tricky assignment and test inside while condition
// this will terminate loop when negative number read
while( (score = in.nextInt()) >= 0) {
count++;
sum = sum + score;
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double)sum/(double)count;
System.out.println("average: " + average);
} // end of main
}
package looppkg;
// ExamScores.java: read scores and calculate average
import java.util.Scanner;
public class ExamScores {
private int score;
private int sum;
private int count;
private Scanner in;
public ExamScores() {
sum = 0;
count = 0;
in = new Scanner(System.in);
}
public double inputAndAverage() {
double average;
// this will terminate loop when negative number read
while ( (score = in.nextInt()) > 0) {
count++;
sum = sum + score;
}
System.out.println("count: " + count + ", sum: " + sum);
average = (double) sum / (double) count;
return average;
}
}
package looppkg;
public class ExamScoresMain {
public static void main(String[] args) {
ExamScores examScores = new ExamScores();
double average = examScores.inputAndAverage();
System.out.println("Average: " + average);
}
}