|
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 ibarlandradford.edu |