Chapter 6

Controlling Program Flow with Loops

In This Chapter

arrow Using basic looping

arrow Counting as you loop

arrow Repeating relentlessly (until the user gives you a clear answer)

In 1966, the company that brings you Head & Shoulders shampoo made history. On the back of the bottle, the directions for using the shampoo read, “LATHER-RINSE-REPEAT.” Never before had a complete set of directions (for doing anything, let alone shampooing your hair) been summarized so succinctly. People in the direction-writing business hailed this as a monumental achievement. Directions like these stood in stark contrast to others of the time. (For instance, the first sentence on a can of bug spray read, “Turn this can so that it points away from your face.” Duh!)

Aside from their brevity, the thing that made the Head & Shoulders directions so cool was that, with three simple words, it managed to capture a notion that’s at the heart of all instruction-giving — the notion of repetition. That last word, REPEAT, took an otherwise bland instructional drone and turned it into a sophisticated recipe for action.

The fundamental idea is that when you’re following directions, you don’t just follow one instruction after another. Instead, you take turns in the road. You make decisions (“If HAIR IS DRY, then USE CONDITIONER,”) and you go into loops (“LATHER-RINSE, and then LATHER-RINSE again.”). In computer programming, you use decision making and looping all the time. This chapter explores looping in Java.

Repeating Instructions Over and Over Again (Java while Statements)

Here’s a guessing game for you. The computer generates a random number from 1 to 10. The computer asks you to guess the number. If you guess incorrectly, the game continues. As soon as you guess correctly, the game is over. Listing 6-1 shows the program to play the game, and Figure 6-1 shows a round of play.

Listing 6-1: A Repeating Guessing Game

  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();
   }
}

9781118407806-fg0601.tif

Figure 6-1: Play until you drop.

In Figure 6-1, the user makes four guesses. Each time around, the computer checks to see whether 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 repeats several statements, checking each time through to see whether the user’s guess is the same as a certain 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. Figure 6-2 illustrates the flow of action.

9781118407806-fg0602.tif

Figure 6-2: Around and around you go.

When you look over Listing 6-1, you see the code that does all this work. At the core of the code is a thing called a while statement (also known as a while loop). Rephrased in English, the while statement says:

  while the inputNumber is not equal to the randomNumber
keep doing all the stuff in curly braces: {


}

The stuff in curly braces (the stuff that repeats) is the code that prints Try again and Enter an int..., gets a value from the keyboard, and adds 1 to the count of the user’s guesses.

tip.eps When you’re dealing with counters, like numGuesses in Listing 6-1, you may easily become confused and be off by 1 in either direction. You can avoid this headache by making sure that the ++ statements stay close to the statements whose events you’re counting. For example, in Listing 6-1, the variable numGuesses starts with a value of 0. That’s because, when the program starts running, the user hasn’t made any guesses. Later in the program, right after each call to keyboard.nextInt, is a numGuesses++ statement. That’s how you do it — you increment the counter as soon as the user enters another guess.

The statements in curly braces are repeated as long as inputNumber != randomNumber is true. Each repetition of the statements in the loop is called an iteration of the loop. In Figure 6-1, the loop undergoes three iterations. (If you don’t believe that Figure 6-1 has exactly three iterations, count the number of Try again printings in the program’s output. A Try again appears for each incorrect guess.)

When, at long last, the user enters the correct guess, the computer goes back to the top of the while statement, checks the condition in parentheses, and finds itself in double double-negative land. The not equal (!=) relationship between inputNumber and randomNumber no longer holds. In other words, the while statement’s condition, inputNumber != randomNumber, is false. Because the while statement’s condition is false, the computer jumps past the while loop and goes on to the statements just below the while loop. In these two statements, the computer prints You win after 4 guesses.

remember.eps With code of the kind shown in Listing 6-1, the computer never jumps out in mid-loop. When the computer finds that inputNumber isn’t equal to randomNumber, the computer marches on and executes all five statements inside the loop’s curly braces. The computer performs the test again (to see whether inputNumber is still not equal to randomNumber) only after it fully executes all five statements in the loop.

Repeating a Certain Number of Times (Java for Statements)

“Write ‘I will not talk in class’ on the blackboard 100 times.”

What your teacher really meant was,

  Set the count to 0.
As long as the count is less than 100,
   Write 'I will not talk in class' on the blackboard,
   Add 1 to the count.

Fortunately, you didn’t know about loops and counters at the time. If you pointed out all this stuff to your teacher, you’d have gotten into a lot more trouble than you were already in.

One way or another, life is filled with examples of counting loops. And computer programming mirrors life — or is it the other way around? When you tell a computer what to do, you’re often telling the computer to print three lines, process ten accounts, dial a million phone numbers, or whatever. Because counting loops is so common in programming, the people who create programming languages have developed statements just for loops of this kind. In Java, the statement that repeats something a certain number of times is called a for statement. Listings 6-2 and 6-3 illustrate the use of the for statement. Listing 6-2 has a rock-bottom simple example, and Listing 6-3 has a more exotic example. Take your pick.

Listing 6-2: The World’s Most Boring for Loop

  import static java.lang.System.out;

public class Yawn {

   public static void main(String args[]) {

      for (int count = 1; count <= 10; count++) {
         out.print("The value of count is ");
         out.print(count);
         out.println(".");
      }

      out.println("Done!");
   }
}

Figure 6-3 shows you what you get when you run the program of Listing 6-2. (You get exactly what you deserve.) The for statement in Listing 6-2 starts by setting the count variable to 1. Then the statement tests to make sure that count is less than or equal to 10 (which it certainly is). Then the for statement dives ahead and executes the printing statements between the curly braces. (At this early stage of the game, the computer prints The value of count is 1.) Finally, the for statement does that last thing inside its parentheses — it adds 1 to the value of count.

9781118407806-fg0603.tif

Figure 6-3: Counting to ten.

With count now equal to 2, the for statement checks again to make sure that count is less than or equal to 10. (Yes, 2 is smaller than 10.) Because the test turns out okay, the for statement marches back into the curly braced statements and prints The value of count is 2 on the screen. Finally, the for statement does that last thing inside its parentheses — it adds 1 to the value of count, increasing the value of count to 3.

And so on. This whole thing repeats until, after 10 iterations, the value of count finally reaches 11. When this happens, the check for count being less than or equal to 10 fails, and the loop’s execution ends. The computer jumps to whatever statement comes immediately after the for statement. In Listing 6-2, the computer prints Done! Figure 6-4 illustrates the whole process.

9781118407806-fg0604.tif

Figure 6-4: The action of the for loop in Listing 6-2.

The anatomy of a for statement

After the word for, you always put three things in parentheses. The first of these three things is called an initialization, the second is an expression, and the third thing is called an update.

  for ( initialization ; expression ; update )

Each of the three items in parentheses plays its own distinct role:

  • The initialization is executed once, when the run of your program first reaches the for statement.
  • The expression is evaluated several times (before each iteration).
  • The update is also evaluated several times (at the end of each iteration).

If it helps, think of the loop as if its text is shifted all around:

  int count = 1
for count <= 10 {
   out.print("The value of count is ");
   out.print(count);
   out.println(".");
   count++
}

You can’t write a real for statement this way. Even so, this is the order in which the parts of the statement are executed.

warning.eps If you declare a variable in the initialization of a for loop, you can’t use that variable outside the loop. For instance, in Listing 6-2, you get an error message if you try putting out.println(count) after the end of the loop.

tip.eps Anything that can be done with a for loop can also be done with a while loop. Choosing to use a for loop is a matter of style and convenience, not necessity.

The world premiere of “Al’s All Wet”

Listing 6-2 is very nice, but the program in that listing doesn’t do anything interesting. For a more eye-catching example, see Listing 6-3. In Listing 6-3, I make good on a promise I made in Chapter 5. The program in Listing 6-3 prints all the lyrics of the hit single, “Al’s All Wet.” (You can find the lyrics in Chapter 5.)

Listing 6-3: The Unabridged “Al’s All Wet” Song

  import static java.lang.System.out;

public class AlsAllWet {

  public static void main(String args[]) {

     for (int verse = 1; verse <= 3; verse++) {
      out.print("Al's all wet. ");
      out.println("Oh, why is Al all wet? Oh,");
      out.print("Al's all wet 'cause ");
      out.println("he's standing in the rain.");
      out.println("Why is Al out in the rain?");

      switch (verse) {
      case 1:
        out.println("That's because he has no brain.");
        break;
      case 2:
        out.println("That's because he is a pain.");
        break;
      case 3:
        out.println("'Cause this is the last refrain.");
        break;
      }

      switch (verse) {
      case 3:
        out.println("Last refrain, last refrain,");
      case 2:
        out.println("He's a pain, he's a pain,");
      case 1:
        out.println("Has no brain, has no brain,");
      }

      out.println("In the rain, in the rain.");
      out.println("Ohhhhhhhh...");
      out.println();
     }

     out.print("Al's all wet. ");
     out.println("Oh, why is Al all wet? Oh,");
     out.print("Al's all wet 'cause ");
     out.println("he's standing in the rain.");
  }
}

Listing 6-3 is nice because it combines many of the ideas from Chapters 5 and 6. In Listing 6-3, two switch statements are nested inside a for loop. One of the switch statements uses break statements; the other switch statement uses fall-through. As the value of the for loop’s counter variable (verse) goes from 1 to 2 and then to 3, all the cases in the switch statements are executed. When the program is near the end of its run and execution has dropped out of the for loop, the program’s last four statements print the song’s final verse.

technicalstuff.eps When I boldly declare that a for statement is for counting, I’m stretching the truth just a bit. Java’s for statement is very versatile. You can use a for statement in situations that have nothing to do with counting. For instance, a statement with no update part, such as for (i = 0; i < 10; ), just keeps on going. The looping ends when some action inside the loop assigns a big number to the variable i. You can even create a for statement with nothing inside the parentheses. The loop for ( ; ; ) runs forever, which is good if the loop controls a serious piece of machinery. Usually, when you write a for statement, you’re counting how many times to repeat something. But, in truth, you can do just about any kind of repetition with a for statement.

ontheweb_fmt.eps Listing 6-3 uses break statements to jump out of a switch. But a break statement can also play a role inside a loop. To see an example, visit this book’s website (www.allmycode.com/JavaForDummies).

Repeating Until You Get What You Want (Java do Statements)

“Fools rush in where angels fear to tread.”

–Alexander Pope

Today, I want to be young and foolish (or, at the very least, foolish). Look back at Figure 6-2 and notice how Java’s while loop works. When execution enters a while loop, the computer checks to make sure that the loop’s condition is true. If the condition isn’t true, the statements inside the loop are never executed — not even once. In fact, you can easily cook up a while loop whose statements are never executed (although I can’t think of a reason why you would ever want to do it).

  int twoPlusTwo = 2 + 2;

while (twoPlusTwo == 5) {
   out.println("Are you kidding?");
   out.println("2 + 2 doesn't equal 5");
   out.print("Everyone knows that");
   out.println(" 2 + 2 equals 3");
}

In spite of this silly twoPlusTwo example, the while statement turns out to be the most versatile of Java’s looping constructs. In particular, the while loop is good for situations in which you must look before you leap. For example, “While money is in my account, write a mortgage check every month.” When you first encounter this statement, if your account has a zero balance, you don’t want to write a mortgage check — not even one check.

But at times (not many), you want to leap before you look. Take, for instance, the situation in which you’re asking the user for a response. Maybe the user’s response makes sense, but maybe it doesn’t. If it doesn’t, you want to ask again. Maybe the user’s finger slipped, or perhaps the user didn’t understand the question.

Figure 6-5 shows some runs of a program to delete a file. Before deleting the file, the program asks the user whether making the deletion is okay. If the user answers y or n, the program proceeds according to the user’s wishes. But if the user enters any other character (any digit, uppercase letter, punctuation symbol, or whatever), the program asks the user for another response.

9781118407806-fg0605.tif

Figure 6-5: Two runs of the code in Listing 6-4.

To write this program, you need a loop — a loop that repeatedly asks the user whether the file should be deleted. The loop keeps asking until the user gives a meaningful response. Now, the thing to notice is that the loop doesn’t need to check anything before asking the user the first time. Indeed, before the user gives the first response, the loop has nothing to check. The loop doesn’t start with “as long as such-and-such is true, then get a response from the user.” Instead, the loop just leaps ahead, gets a response from the user, and then checks the response to see whether it makes sense.

That’s why the program in Listing 6-4 has a do loop (also known as a do … while loop). With a do loop, the program jumps right in, takes action, and then checks a condition to see whether the result of the action makes sense. If the result makes sense, execution of the loop is done. If not, the program goes back to the top of the loop for another go-around.

Listing 6-4: To Delete or Not to Delete

  import java.io.File;
import static java.lang.System.out;
import java.util.Scanner;

public class DeleteEvidence {

  public static void main(String args[]) {
     File evidence = new File("cookedBooks.txt");
     Scanner keyboard = new Scanner(System.in);
     char reply;

     do {
       out.print("Delete evidence? (y/n) ");
       reply =
         keyboard.findWithinHorizon(".",0).charAt(0);
     } while (reply != 'y' && reply != 'n'),

     if (reply == 'y') {
       out.println("Okay, here goes...");
       evidence.delete();
       out.println("The evidence has been deleted.");
     } else {
       out.println("Sorry, buddy. Just asking.");
     }

     keyboard.close();
  }
}

Figure 6-5 shows two runs of the code in Listing 6-4. The program accepts lowercase letters y and n, but not the uppercase letters Y and N. To make the program accept uppercase letters, change the conditions in the code as follows:

  do {
   out.print("Delete evidence? (y/n) ");
   reply = keyboard.findWithinHorizon(".", 0).charAt(0);
} while (reply != 'y' && reply != 'Y' &&
       reply != 'n' && reply!='N');
    
if (reply == 'y' || reply == 'Y') {

Figure 6-6 shows the flow of control in the loop of Listing 6-4. With a do loop, the situation in the twoPlusTwo program (shown at the beginning of this section) can never happen. Because the do loop carries out its first action without testing a condition, every do loop is guaranteed to perform at least one iteration.

9781118407806-fg0606.tif

Figure 6-6: Here we go loop, do loop.

tip.eps The location of Listing 6-4's cookedBooks.txt file on your computer's hard drive depends on several things. If you create a cookedBooks.txt file in the wrong directory, then the code in Listing 6-4 cannot delete your file. (More precisely, if cookedBooks.txt is in the wrong directory on your hard drive, then the code in Listing 6-4 can't find the cookedBooks.txt file in preparation for deleting the file.) In most settings, you start testing Listing 6-4 by creating a project within your IDE. The new project lives in a folder on your hard drive, and the cookedBooks.txt file belongs directly inside that folder. For example, with the Eclipse IDE, I have a project named Listing06-04. That project lives on my hard drive in a folder named c:Usersmy-user-nameworkspaceListing06-04. Inside that folder, I have a file named cookedBooks.txt (until I delete the file with the code in Listing 6-4). Also in that Listing06-04 folder I have a subfolder named src. My DeleteEvidence.java file is directly inside that Listing06-04 folder.

cross-reference.eps For more information about files and their folders, see Chapter 8.

Reading a single character

Back in Listing 5-3 from Chapter 5, the user types a word on the keyboard. The keyboard.next method grabs the word and places the word into a String variable named password. Everything works nicely because a String variable can store many characters at once, and the next method can read many characters at once.

But in Listing 6-4, you’re not interested in reading several characters. You expect the user to type one letter — either y or n. So you don’t create a String variable to store the user’s response. Instead, you create a char variable — a variable that stores just one symbol at a time.

The Java API doesn’t have a nextChar method. So to read something suitable for storage in a char variable, you have to improvise. In Listing 6-4, the improvisation looks like this:

  keyboard.findWithinHorizon(".", 0).charAt(0)

You can use this code exactly as it appears in Listing 6-4 whenever you want to read a single character.

remember.eps A String variable can contain many characters or just one. But a String variable that contains only one character isn’t the same as a char variable. No matter what you put in a String variable, String variables and char variables have to be treated differently.

File handling in Java

In Listing 6-4, the actual file-handling statements deserve some attention. These statements involve the use of classes, objects, and methods. Many of the meaty details about these things are in other chapters, like Chapters 7 and 9. Even so, I can’t do any harm by touching on some highlights right here.

So, you can find a class in the Java language API named java.io.File. The statement

  File evidence = new File("cookedBooks.txt");

creates a new object in the computer’s memory. This object, formed from the java.io.File class, describes everything that the program needs to know about the disk file cookedBooks.txt. From this point on in Listing 6-4, the variable evidence refers to the disk file cookedBooks.txt.

The evidence object, being an instance of the java.io.File class, has a delete method. (What can I say? It’s in the API documentation.) When you call evidence.delete, the computer gets rid of the file for you.

Of course, you can't get rid of something that doesn't already exist. When you call the constructor

  File evidence = new File("cookedBooks.txt");

Java doesn't check to make sure that you have a file named cookedBooks.txt. To force Java to do the checking, you have a few options. The simplest is to call the exists method. When you call evidence.exists(), the method looks in the folder where Java expects to find cookedBooks.txt. The call evidence.exists() returns true if Java finds cookedBooks.txt inside that folder. Otherwise, the call evidence.exists() returns false. Here's a souped-up version of Listing 6-4, with a call to exists included in the code:

  import java.io.File;
import static java.lang.System.out;
import java.util.Scanner;

public class DeleteEvidence {

public static void main(String args[]) {
   File evidence = new File("cookedBooks.txt");
   if (evidence.exists()) {
     Scanner keyboard = new Scanner(System.in);
     char reply;

     do {
      out.print("Delete evidence? (y/n) ");
      reply =
        keyboard.findWithinHorizon(".", 0).charAt(0);
     } while (reply != 'y' && reply != 'n'),

     if (reply == 'y') {
      out.println("Okay, here goes...");
      evidence.delete();
      out.println("The evidence has been deleted.");
     } else {
      out.println("Sorry, buddy. Just asking.");
     }

     keyboard.close();
   }
}
}

Variable declarations and blocks

A bunch of statements surrounded by curly braces forms a block. If you declare a variable inside a block, you generally can’t use that variable outside the block. For instance, in Listing 6-4, you get an error message if you make the following change:

  do {
  out.print("Delete evidence? (y/n) ");
  char reply =
     keyboard.findWithinHorizon(".", 0).charAt(0);
} while (reply != 'y' && reply != 'n'),

if (reply == 'y')

With the declaration char reply inside the loop’s curly braces, no use of the name reply makes sense anywhere outside the braces. When you try to compile this code, you get three error messages — two for the reply words in while (reply != 'y' && reply != 'n') and a third for the if statement’s reply.

So in Listing 6-4, your hands are tied. The program’s first real use of the reply variable is inside the loop. But to make that variable available after the loop, you have to declare reply before the loop. In this situation, you’re best off declaring the reply variable without initializing the variable. Very interesting!

cross-reference.eps To read more about variable initializations, see Chapter 4. To find out more about blocks, see Chapter 5.

All versions of Java have the three kinds of loops described in this chapter (while loops, for loops, and do . . . while loops). But newer Java versions (namely, Java 5 and beyond) have yet another kind of loop called an enhanced for loop. For a look at Java's enhanced for loop, see Chapter 11.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.72.176