![]() |
![]() |
|
home—info—lects—labs—exams—hws
textbook—tutor/PIs—java.lang docs—java.util docs
If we finish these examples, we will talk about:
Recall: to read numbers from the keyboard repeatedly, we could use the Scanner methods hasNextInt() and nextInt():
import java.util.Scanner;
class Lect11 {
void echoNumbers() {
Scanner s = new Scanner( System.in ); // s will gather chars from the keyboard
while (s.hasNextInt()) {
System.out.println( "Read " + s.nextInt() );
// Usually we update our index variable, to update
// our notion of where we are in the process;
// but in this case calling 'nextInt' already udpated
// what characters had been consumed from the input stream.
}
System.out.println( "There isn't an int to read next." );
}
}
|
Task: Read numbers from keyboard (as long as hasNextInt()), and return the largest number typed.
| input typed by the user | expected result of calling maxFromKeyboard |
| 3 17 9 2 21 bye-bye | 21 |
| -3 -17 -9 -2 -21 stoppity-stop | -2 |
| 3 bye-bye | 3 |
| bye-bye | no conceivable answer -- a run-time error perhaps? |
// ATTEMPT 1 -- does not work correctly
// Read the maximum integer typed at the keyboard.
// Keep reading until some non-integer gets typed.
// THERE MUST BE AT LEAST ONE INTEGER TYPED else our program will cause an error.
//
int maxFromKeyboard() {
Scanner s = new Scanner( System.in );
int maxSoFar;
while (s.hasNextInt()) {
if (maxSoFar < s.nextInt()) {
maxSoFar = s.nextInt();
}
// else do nothing.
}
return maxSoFar;
}
|
One problem is that we don't initiailze our accumulator maxSoFar. (If we don't initialize a local, Java won't even let us compile.1)
However, it's not clear what to initialize it to?
Clearly, 0 won't work: our second test case wouldn't pass. (Why not?)
Something like negative infinity would work in this case,
but the technique doesn't generalize (suppose you wanted to
find the minimum-length string that is typed in —
there is no 'infinite-string' value).
A clever solution (possibly inspired by how you'd solve this problem in real life):
Use the very first value, as your maxSoFar!
We know that there is always going to be such a first value
(since max is undefined on the empty sequence of numbers):
// ATTEMPT 2 -- compiles, but still does not work correctly
// Read the maximum integer typed at the keyboard.
// Keep reading until some non-integer gets typed.
// THERE MUST BE AT LEAST ONE INTEGER TYPED else our program will cause an error.
//
int maxFromKeyboard() {
Scanner s = new Scanner( System.in );
int maxSoFar = in.nextInt();
// If there isn't an int to read, the scanner will blow up, but that's okay:
// our comment clearly states there must be at least one integer.
while (s.hasNextInt()) {
if (maxSoFar < s.nextInt()) {
maxSoFar = s.nextInt();
}
// else do nothing.
}
return maxSoFar;
}
|
The solution is pretty easy: store the result of the first s.nextInt() in a variable, and then use that one variable twice:
// ATTEMPT 3 -- works!
// Read the maximum integer typed at the keyboard.
// Keep reading until some non-integer gets typed.
// THERE MUST BE AT LEAST ONE INTEGER TYPED else our program will cause an error.
//
int maxFromKeyboard() {
Scanner s = new Scanner( System.in );
int maxSoFar = in.nextInt();
// If there isn't an int to read, the scanner will blow up, but that's okay:
// our comment clearly states there must be at least one integer.
while (s.hasNextInt()) {
int currentNum = s.nextInt();
if (maxSoFar < currentNum) {
maxSoFar = currentNum;
}
// else do nothing.
}
return maxSoFar;
}
|
design principle: A method should either return a value or mutate state, but not both.
(Use two different methods — a getter and a mutator — if you want to do these two different things.)
while (s.hasNextInt()) {
maxSoFar = Math.max( maxSoFar, s.nextInt() );
}
|
1 However if you ever have a constructor which doesn't initialize a field, Java will let you compile in that case; then Java will initialize all your fields to "a zero-ish value" for you. If you ever see a nullPointerException it means you're using a field you never initialized. It is sound practice to always initialize all your fields yourself — if nothing else, you'll never have to look at your code later and wonder “gee, did I intend to leave the field uninitialized, or is there a latent bug hiding in this program?”. ↩
home—info—lects—labs—exams—hws
textbook—tutor/PIs—java.lang docs—java.util docs
| ©2009, Ian Barland, Radford University Last modified 2009.Apr.08 (Wed) |
Please mail any suggestions (incl. typos, broken links) to ibarland |
![]() |