Java Programming and Loop Iterations

By Barry Burd

To make your Java program’s loops easier to write and easier to understand, you need to know how Java’s break and continue statements affect loop iterations.

Java’s break statement

Take a gander at the program below. The program randomly generates a number from 1 to 10, and repeatedly asks the user to guess that number.

Listing 1

import static java.lang.System.out;
import java.util.Scanner;
import java.util.Random;
public class GuessAgain {
    public static void main(String args[]) {
        Scanner keyboard = new Scanner(System.in);
        int numGuesses = 0;
        int randomNumber = new Random().nextInt(10) + 1;
        out.println("       ************         ");
        out.println("Welcome to the Guessing Game");
        out.println("       ************         ");
        out.println();
        out.print("Enter an int from 1 to 10: ");
        int inputNumber = keyboard.nextInt();
        numGuesses++;
        while (inputNumber != randomNumber) {
            out.println();
            out.println("Try again...");
            out.print("Enter an int from 1 to 10: ");
            inputNumber = keyboard.nextInt();
            numGuesses++;
        }
        out.print("You win after ");
        out.println(numGuesses + " guesses.");
        keyboard.close();
    }
}

The figure below shows a run of the code. The user makes five guesses. Each time around, the computer checks to see if the guess is correct. An incorrect guess generates a request to try again. For a correct guess, the user gets a rousing You win, along with a tally of the number of guesses he or she made. The computer is repeating several statements over and over again, checking each time through to see if the user’s guess is the same as the randomly generated number. Each time the user makes a guess, the computer adds 1 to its tally of guesses. When the user makes the correct guess, the computer displays that tally.

image0.jpg

What’s awkward about this program? Well, a few statements appear more than once in the program. Normally, a statement that’s copied from one part of a program to another is no cause for concern. But, the overall strategy seems suspicious. The program gets a number from the user before the loop and (again) inside the loop.

out.print("Enter an int from 1 to 10: ");
int inputNumber = keyboard.nextInt();
numGuesses++;
while (inputNumber != randomNumber) {
    out.println();
    out.println("Try again...");
    out.print("Enter an int from 1 to 10: ");
    inputNumber = keyboard.nextInt();
    numGuesses++;
}

This code uses a standard trick for making loops work. It’s called priming a loop. The pattern is

Get input
while the input you have isn’t the last input
{
   Get more input
}

At the very start of the while loop, the computer checks a condition having to do with the user’s input. So the computer doesn’t enter the loop until the user gives some input. Then when the computer is inside the loop, the computer asks for more input to feed the loop’s next iteration. The trick seems strange, but it works.

Developers use this technique, priming a loop, all the time, so it can’t be that bad. But there is another way.

Listing 2

import static java.lang.System.out;
import java.util.Scanner;
import java.util.Random;
public class GuessAgain {
    public static void main(String args[]) {
        Scanner keyboard = new Scanner(System.in);
        int inputNumber, numGuesses = 0;
        int randomNumber = new Random().nextInt(10) + 1;
        out.println("       ************         ");
        out.println("Welcome to the Guessing Game");
        out.println("       ************         ");
        out.println();
        while (true) {
            out.print("Enter an int from 1 to 10: ");
            inputNumber = keyboard.nextInt();
            numGuesses++;
            if (inputNumber == randomNumber) {
                break;
            }
            out.println();
            out.println("Try again...");
        }
        out.print("You win after ");
        out.println(numGuesses + " guesses.");
        keyboard.close();
    }
}

From the user’s point of view, the code in Listing 2 does exactly the same thing as the code in Listing 1. (To see the output of either program, refer to the figure above.) The difference is Listing 2 has only one call to keyboard.nextInt. That call is inside the loop, so the computer must enter the loop without testing any input.

If you look at the loop’s condition, you can see how this works. The loop’s condition is always true. No matter what’s going on, the loop’s condition always passes its test. So the loop’s condition is a big fraud. You never jump out of the loop by failing the test in the loop’s condition. Instead, you jump out when you hit the break statement that’s inside the loop (and you hit that break statement when you get past the if (inputNumber == randomNumber) roadblock). The whole thing works very nicely.

When the computer executes a break statement that’s in a loop, the computer jumps out of the loop (to the first statement that comes after the loop).

With a break statement, the computer jumps out of only one loop. If that loop happens to be inside another loop (an outer loop) the computer doesn’t jump outside of the outer loop.

public class BreakOutOfLoop {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 100; j++) {
                System.out.print(j + " ");
                if (j > 9) {
                    break;
                }
            }
            System.out.println(" I broke out!");
        }
    }
}

To illustrate, the following figure contains the output of the preceding code:

image1.jpg

When the computer reaches the break statement, control jumps to the I broke out statement. That I broke out statement is outside of the for j loop but it’s inside the for i loop.

From a programmer’s point of view, the code in Listing 2 is more natural than the code in Listing 1. After all, how does the game proceed? The user guesses, then the computer checks the guess, and then (if the guess isn’t correct) the computer says “Try again.” That’s the sequence of events as described in Listing 2. But in Listing 1, the code inside the loop seems to describe the happenings in reverse order: The loop says “Try again,” and then the user inputs a number.

Listing 2 offers a nice alternative to the loop-priming technique in Listing 1. So why do programmers bother to prime their loops? Do break statements have any hidden drawbacks? Well, the answer depends on your point of view. Some programmers think that break statements in loops are confusing. All the jumping from statement to statement makes them dizzy and reminds them of something from the 1960s called spaghetti code. (Spaghetti code uses goto statements to jump from one statement to another. In Pascal by Example, author B. Burd says “Programming with goto is like traveling around Paris by swimming through its sewer system. There are plenty of short cuts, but none of them are worth taking.”) One way or another, break statements in loops are the exception, not the rule. Use them if you want, but don’t expect to find many of them in other people’s Java code.

Java’s continue statement

Listing 3 offers more secret sauce for your program’s loops. Imagine a game that randomly generates three numbers from 1 to 20. The user takes five turns guessing the numbers. When the user enters a correct guess, the program congratulates the user. (“Good guess,” says the program.) When the user enters an incorrect guess, the program provides no feedback.

Listing 3 contains some code to make it all happen.

Listing 3

import static java.lang.System.out;
import java.util.Scanner;
import java.util.Random;
public class GuessAgainAndAgain {
    public static void main(String args[]) {
        Scanner keyboard = new Scanner(System.in);
        int inputNumber;
        int randNum1 = new Random().nextInt(20) + 1;
        int randNum2 = new Random().nextInt(20) + 1;
        int randNum3 = new Random().nextInt(20) + 1;
        out.println("       ************         ");
        out.println("Welcome to the Guessing Game");
        out.println("       ************         ");
        out.println();
        for (int i = 0; i < 5; i++) {
            out.print("Enter an int: ");
            inputNumber = keyboard.nextInt();
            if (inputNumber != randNum1 && 
                inputNumber != randNum2 &&
                inputNumber != randNum3)    {
              
                continue;
            
            }
            out.println("Good guess!");
            out.println();
        }
        out.print("The numbers are ");
        out.print(randNum1 + " ");
        out.print(randNum2 + " ");
        out.print(randNum3 + " ");
        keyboard.close();
    }
}

This figure shows a run of such a program.

image2.jpg

Java’s continue statement tells the computer to jump past the remaining statements inside the loop. That is, instead of executing the remaining statements inside the loop, the computer moves on to the start of the next iteration of the loop. So, in Listing 3, when the inputNumber isn’t any of the program’s randomly generated numbers, the computer jumps past the “Good guess” code, increments the loop counter (the variable i), and asks the user for another input value. (Of course, if the loop counter hits its limit, the computer doesn’t execute another iteration. Instead, the computer jumps out of the loop, and executes whatever statements come after the loop.)

You can easily rewrite Listing 3 so that the code has no continue statement. You’d have to put the “Good guess” code inside an if statement, but that would be okay. The continue statement doesn’t do much to improve the look of the Listing 3 program. But when you want avoid nesting code inside if statements, the continue statement comes in handy.

Maybe, in your application, the remainder of the loop is a complicated sequence of statements. You don’t want to make this sequence seem more complicated by enclosing it inside an if statement. Or perhaps, in your app, you only rarely skip the remainder of the loop, and you want to emphasize this rarity by not enclosing the remainder of the loop in an if statement. In either case, a continue statement might be exactly the right choice.