Session 15: More about loops

The do loop (Section 8.3)
The continue statement (Section 8.4)
Labeled break and continue statements (Section 8.5)
On the usefulness thereof
Exercise

The do loop

Textbook: Section 8.3

We've already seen the while loop and the for loop. This is the final type of loop available in Java: The do loop. It's useful when you have a while loop, but you always want the first iteration to occur. For example, you might have handled the Nim program as follows.

import csbsju.cs160.*;

public class Nim {
    public static void main(String[] args) {
        String line;
        do {
            playGame();
            IO.print("again (y/n)? ");
            line = IO.readLine();
        } while(line.startsWith("y"));
    }
}

Notice that I had to define line outside the loop. If it was declared when it is assigned a value (the line calling IO.readLine(), the variable wouldn't be visible within the condition on the following line, since that condition follows the closing brace within which the declaration would be.

The continue statement

Textbook: Section 8.4

We've seen how the break statement will terminate a loop prematurely. The continue statement is related: It tells the compute to skip the body of the loop, but to test to see whether to continue through another iteration.

InputFile f = new InputFile("input");
int total = 0;
while(true) {
    String line = f.readLine();
    if(line == null) break;
    if(line.startsWith("#")) {
        IO.println("line commented out");
        continue;
    }
    total += Integer.parseInt(line);
}
System.out.println(total);
The above program sums up all the numbers in a file, but it ignores lines beginning with '#' - essentially, the '#' works as a way of adding comments to the file.

In a for loop, the update clause will still be executed when a continue statement is encountered.

InputFile f = new InputFile("input");
int total = 0;
for(int line_num = 1; ; line_num++) {
    String line = f.readLine();
    if(line == null) break;
    if(line.startsWith("#")) {
        IO.println("line " + line_num + " commented out");
        continue;
    }
    total += Integer.parseInt(line);
}
In this program, the line_num++ is executed even when the line begins with ``#.''

Labeled break and continue statements

Textbook: Section 8.5

What happens when you have one loop within another, and within the inner loop you want to break out of both? If you just type ``break,'' the computer will stop executing the inner loop and continue through the iteration of the outer loop.

The solution is the labeled break statement, which allows you to give a loop a name, which can then be named when you do the break. The following code searches an array to see if it has any duplicates.

    boolean has_duplicate = false;
outer_loop:
    for(int i = 0; i < arr.length; i++) {
        for(int j = i + 1; j < arr.length; j++) {
            if(arr[i] == arr[j]) {
                has_duplicate = true;
                break outer_loop;
            }
        }
    }

You can do the same sort of thing with continue statements, where you label the loop of which you wish to go to the next iteration.

On the usefulness thereof

These constructs we've discussed today - the do loop, the continue statement, and the labeled break statement are much less frequently used than the other loop concepts we've discussed so far. To get a feel for how useful they are, I counted how often different statements occurred in the code for Logisim and the 150 CPU simulator, which together contain 12,000 lines of code.

while loop122 times
for loop120 times
do loop0 times
break statement166 times
continue statement3 times
labeled break or continue0 times

Exercise

(This has nothing to do with anything of the above.)

Consider the following Tokenizer class to help with finding a sequence of words within a string. (You'll need to copy and paste this into BlueJ.)

public class Tokenizer {
    private String remaining; // words yet to be returned

    // (Constructor method) Constructs a Tokenizer for extracting
    // a sequence of words from !sentence!.
    public Tokenizer(String sentence) {
        remaining = sentence;
    }

    // Returns the next word found in the sentence.
    public String nextToken() {
        int space = remaining.indexOf(" ");
        if(space < 0) {
            // no more spaces are in the string; this is the last word
            String ret = remaining;
            remaining = "";
            return ret;
        } else {
            // take the first word off the string and return it
            String ret = remaining.substring(0, space);
            remaining = remaining.substring(space + 1);
            return ret;
        }
    }

    // Returns true if there are any more words remaining in the
    // sequence yet to be returned.
    public boolean hasMoreTokens() {
        return !remaining.equals("");
    }
}

Using this Tokenizer class, write a new class FindBWords containing a run() class method, which reads a line from the user and prints the words within it that begin with a capital B.

Beware the Jubjub Bird and shun the frumious Bandersnatch.
Beware
Bird
Bandersnatch
END OF WORDS