FAQ: Using next.. methods in loops.

Using next... and hasNext... methods in loops:

(Heidi Newton)

Based on frequently asked questions to the online help. If you need help with your assignment specific to the code you have wrote, and your question isn't answered here, look at the instructions in the sticked "Getting help on the assignments" thread by pondy.

The key thing to remember is that you have a list of numbers in the user input e.g. 34 7 23 28 48 98 71 95 33 25

Each time you call UI.nextDouble() it will return and remove the next double from the input. i.e. (using the above data)
UI.println("call 1 is: " + UI.nextDouble());
UI.println("call 2 is: " + UI.nextDouble());
UI.println("call 3 is: " + UI.nextDouble());
Would output

call 1 is: 34
call 2 is: 7
call 3 is: 23

So once you call UI.nextDouble(), that next input number is removed.

(In this case, using printf rather than println would have probably been better. However, I have stayed away from printf for examples like this since it just adds to the confusion!)

This can lead to a few pitfalls that I have seen a number of times both this year and last. For this example, lets just assume we have a program that a user enters a bunch of numbers, and they want both the product (multiply them together) and the sum (add them together) of them. If you did something like this...

...
double sum = 0;
double product = 1; // When we multiply numbers together we have to start with 1 (just incase anybody is confused about the 1)
while (UI.hasNextDouble()) {
   sum = sum + UI.nextDouble();
   product = product * UI.nextDouble();
UI.println("The sum is: " + sum + " and the product is " + product);

This program is NOT going to do what you probably expected it to do!
In the first loop iteration, sum will become 0 + 34 (the result of the first call to UI.nextDouble()) making it 34.
And then still in the first iteration, product will become 1 * 7 (the result of the second call to UI.nextDouble()) making it 7

Why was product not 1 * 34?
What has happened is that the first call to UI.nextDouble() returned and removed 34 from the input. Now that the 34 is gone, the first one is 7, so the second call returned and removed 7 from the input.
The sum would be 34 + 23 + 48 + 71 + 33
And the product would be 7 * 28 * 98 * 95 * 25
Not what you wanted!!

So, how can we fix this code?
We can use a variable to store the result of the call to UI.nextDouble() i.e...
double sum = 0;
double product = 1;
while (UI.hasNextDouble()) {
   double nextNumber = UI.nextDouble();
   sum = sum + nextNumber;
   product = product * nextNumber;
UI.println("The sum is: " + sum + " and the product is " + product);

And now this will do what you probably expect!
The sum will be the sum of ALL the numbers, and the product will be the product of ALL the numbers.
Basically, to allow the next number in the input to be used more than once (as calling nextDouble() more than once won't work, as we saw above!), you can store it in a variable like I have done.

This might be useful for your stock analyser program, seeing as you have to use the same numbers to calculate several different things.

Also, this one seems to be a VERY common trap, and a little subtle...

double nextNumber = UI.nextDouble();
double sum = 0;
while (UI.hasNextDouble) {
    nextNumber = UI.nextDouble();
    sum = sum + nextNumber;
UI.println("The sum is " + sum);
 

What has happened here is that you put the first value from the input into nextNumber before the loop, then you put the second one in when the loop started, and then added it to the sum... the first number from the input was lost!

The result is that the sum is all the numbers except the first one (so if this is happening in your stock analyser... check if you are accidentally not using the result of the first call to UI.nextDouble()!!!

Even if you do this, there is still a small bug!

double nextNumber = UI.nextDouble();
double sum = 0;
while (UI.hasNextDouble) {
    sum = sum + nextNumber;
    nextNumber = UI.nextDouble();
UI.println("The sum is " + sum);
 

This will add all the numbers, as you are putting the first one into nextNumber, then adding it to the sum in the loop, then getting the second one and adding it, etc.
Except... if there was only 1 number, you will put it in nextNumber before the loop, and then when it gets to the loop it will see no more doubles in the input, meaning UI.hasNextDouble() will return false, the loop will never run, and the 1 value will never be processed!

You don't always need to get the first value out BEFORE the loop. Only do it when you HAVE to. In particular, you need to when your loop condition is putting more specific requirements on the data you are getting from the user than simply "it exists" (e.g. the strings must start with e, or the numbers must be divisible by 2). This is so that you have the value so that you can actually do these checks on it.

When you are just going to be using UI.hasNextDouble() or UI.hasNext(), there is no need to get the value out before the loop, as you don't need to check anything about it to ensure the loop should continue.