15-100 Lecture 8 (June 6, 2006)

A Quick review of the "if statement"

Last class, we discussed the "if statment". Complete with an "else" clause, it has the following form:

  if (predicate) {
    // the code here executes if the predicate is true
  } else {
    // the code here executes if the predicate is false
  }
  

The "predicate" is a boolean expression. In other words, it is something that evaluates to true or false. Consider the example below:

  if (bodyTemp > 98.6) {
    System.out.println ("You have a fever.");
  } else {
    System.out.println ("Normal body tempurature.");
  }
  

Please also recall that the "else" clause is optional. For example, consider the example below:

  if (availableCredit < purchasePrice) {
    System.out.println ("Sorry. You've exceeded your available credit.");
    return;
  }

  availableCrdit -= purchasePrice;
  makePurchase(purchasePrice);
  

The "while" loop

It is often times useful to repeat an operation until certain criteria are met. We see this in the real world every day. As long as you can see dirt, keep vacuming. While the roast is below safe tempurature, keep cooking.

We also see this in computer programs. For example, we might continue to read from a file as long as we haven't gotten to the end. Or, we might process user input so long as they don't select "Q" for quit.

Java has a langauge feature for exactly this -- the "while" loop. It is one of Java's three loop constructs. It is, perhaps, the most fundamental loop -- and the first that we'll study. Its syntax is strikingly similar to that of the "if" statement:

  while (predicate) {
    // This body is "gated" by the predicate above. 
    // After it completes, control "loops" back to the evaluation 
    // of the predicate
  }
  

Let's consider the example below. It will continue until the user enters a blank line:

  String userInput;

  System.out.print ("Enter line: ");
  while ((userInput = br.readLine().equals("")) {
    System.out.println ("You entered: " + userInput);

    System.out.print ("Enter line: ");
  }
  

Please also consider the following example, which prints number 1, 2, 3, 4, ..., 10.

  int number=1;
  while (number <= 10) {

    System.out.println (number);
  
    number++; // number = number +1;
  }

  // For reference, notice number is 11 after the loop. 
  // (11 > 10) broke the loop, so it stopped after reaching 11, but
  // before re-entering the loop
  System.out.println (number); 
  

The "do...while" loop

The "while loop" is a "precondition" loop. It checks a predicate before entering the loop the first time, and before entering each time thereafter.

Java has a similar loop, called the "do while" loop. It resembles the "while loop", except it checks the predicate after completing the body of the loop. As a result, the loop is guaranteed to run at least once.

Let's reconsider the userinput example from above -- this time as a do-while loop:

  String userInput;

  do {
    boolean continue = true;

    System.out.print ("Enter line: ");
    userInput = br.readLine());

    if (userInput.equals("")) {
      continue = false;
    } else {
      System.out.println ("You entered: " + userInput);
    }
  } while (continue);
  

== vs. .equals()

Let's take a quick look at one of the new details from the code above

  if (userInput.equals("")) {
  

Please notice the funny way that we compared two strings, userInput and "". We'll talk more about this later. But, for right now, the important thing is that you should not compare Strings with the ==-operator. It will not produce reliable results. Instead, you should use the syntax you see below:

  string1.equals(string2)
  

equals() is a method, somewhat like those we have been writing. But, unlike our methods, it isn't "static" -- it actually part of the String. What we are actually doing here is asking "string1" to determine if it is equal to "string2".

Again, we'll discuss the reason for this very soon. For right now, just keep this in mind: Use .equals(), not ==, to determine if two strings are equivalent.

The for loop

Let's consider the example of the quiz one more time. Take another look at it. Notice that there are really four parts:

This idiom is extremely common in programming. As a result, Java has a special loop construct to support it, the "for loop". The for loop is no more or less powerful than the while loop. In the mathematical sense, it is completely equivalent. But, as a matter of practice, choosing the right loop can make our code much more readable.

Let me introduce the for loop by way of example. Consider the following rewritten version of the loop above:

  for (int number=0; number <= 10; number++) {
    System.out.println (number);
  }
  

Do you see the relationship between the elements of the for loop and those of the while loop? Below is the general form of the for loop:

  for (initialization; predicate; increment) {
    body
  }
  

It is perfectly legal for any or all of the initialization, predicate, or increment to be empty. For example, consider the following example of a degenerate form of the for loop, which is exactly equivalent to the while loop:

  int number = 10;
  for (  ; number <= 10; ) {
    System.out.println (number);

    number++;
  }
  

Choosing the Right Loop

By selecting a for loop, when appropriate, we can make immediately clear to the reader:

By choosing a while loop, where appropriate, we can make immediately clear to the reader that:

break

What happens if we want to end a loop "early", without returning to the predicate? A "break" statement exists for this purpose. If a "break" occurs within a loop, the loop immediately ends. The code within the loop, after the break, does not get executed. And, the loop doesn't start over. It just ends. The flow of control picks up right after the loop.

Please consider the following typical example:

  String userInput;

  while (true) {
    System.out.println ("Enter the next number, or a blank line to quit.");
    userInput = br.readLine();

    if (userInput.equals(""))
      break;

    System.out.println ("You entered: " + userInput);
  }

  System.out.println ("Thanks for playing!");
  

Notice how the break allowed us to test a condition within the loop. It can also be combined with a predicate:

  System.out.println ("Please enter up to 10 numbers or a blank line to quit");
 
  for (int number=0; number <=10; number++) {
    System.out.print ("Enter number" + number + ": ");

    String userInput = br.readLine();

    if (userInput.equals(""))
      break;

    System.out.println ("For number" + number + ", you entered: " + userInput);
  }

  System.out.println ("Thanks for playing!");
  

continue

The break statement, as described above, immediately takes the flow of control out of a loop. By contrast, the continue statement causes the flow of control to go immediately back to the "top" of the loop, where the predicate is evaluated. If a continue is reached, the subsequent code is not executed, the increment of a for loop doesn't occur. Instead, "without passing go or collecting $500", control returns immediately to the top of the loop.

Please consider the example below:

  System.out.println ("Please enter five numbers between 1 and 10...");

  for (int count=0; count <= 5; count++) {
    System.out.print ("Please enter number " + count + ": ");
   
    int number = Integer.parseInt (br.readLine());

    // Note: This may be the first time you've seen ||
    // it means logical OR, in other words either-or, or at least one
    if ( (number < 1) || (number > 10) ) {
      System.out.println ("" + number + " isn't between 1 and 10, inclusive.");
      continue; // Back to the top, the "count" control variable will be unchanged
    }

    System.out.println ("Number " + count + " is " + number + ".");

    
  }