CS 4:  Lecture 6
                           Monday, February 6, 2006

LOOPS
=====
To do anything really interesting with a computer, you need a way to repeat an
operation over and over.  A _loop_ is a code sequence that is executed
repeatedly.

"while" Loops
-------------
Java has several types of loops.  The simplest is called a "while" loop.

  long i = 1;
  while (i <= 4) {
    System.out.println(i);              \  These lines inside the braces
    i++;                                /  are called the _loop_body_.
  }

The expression "i <= 4" is the _loop_condition_.  It must always be a boolean.

Here's how the loop executes.
- When Java reaches this "while" loop, it checks whether "i <= 4" is true.
- If i <= 4, Java executes the loop body (the code inside the braces).
- When Java finishes the code inside the braces (i.e. after executing "i++"),
  it checks _again_ whether "i <= 4" is true.
- If it's still true, Java jumps back up to the beginning of the loop body and
  executes it again.
- If Java reaches the end of the loop body and "i <= 4" is false, Java will
  continue execution with the next line of code _after_ the loop body.

So long as "i <= 4" is true, Java repeatedly executes the code inside the
braces.  Java cannot exit the loop until i > 4.

Take a few minutes to pretend that you're the Java intepreter.  Walk through
the code line by line, in the order Java executes it, and execute each line
yourself.  To learn how to program, you will need the ability to pretend you're
Java and execute a program just like Java does.

The code prints the following output.

  1
  2
  3
  4

When Java finally leaves the loop, the variable i contains a 5.

An _iteration_ is a pass through the loop body.  In this example, Java executed
four iterations of the loop body.

If the loop condition is false when Java first reaches the "while" loop, the
loop body doesn't execute even once.  So the following code prints nothing.

  long i = 8;
  while (i <= 4) {
    System.out.println(i);
    i++;
  }

"do" Loops
----------
A "do" loop has just one difference from a "while" loop.  If Java reaches
a "do" loop, it _always_ executes the loop body at least once.  Java doesn't
check the loop condition until the end of the first iteration.

Let's look at a program that repeatedly reads a string from the keyboard, then
prints it back out.  For now, just look at the "do" loop; I'll explain the rest
shortly.

  import java.io.*;

  class SimpleIO {
    public static void main (String[] args) throws Exception {
      BufferedReader keybd = 
            new BufferedReader(new InputStreamReader(System.in));
      String input;

      do {
        input = keybd.readLine();
        System.out.println("You typed " + input);
      } while (!input.equals("stop"));
    }
  }

The body of the "do" loop does two things.  First, it reads a String from the
keyboard.  The "readLine" method waits for you to type a String at the console;
when you hit the "Enter" key, the program can continue.  Second, the "println"
method prints the String you typed in.

The loop condition, `!input.equals("stop")', is true if you did _not_ type
"stop" at the keyboard.  The "!" operator, or _not_ operator, changes a true to
a false or a false to a true.  If you typed any string other than "stop", Java
will jump back to the beginning of the loop body and wait for you to type in
another String.  If you type "stop", then Java prints "stop", exits the loop,
and ends the program.

It makes sense to use a "do" loop instead of a "while" loop here, because the
variable "input" is not initialized until the loop body executes.

Input Classes
-------------
What about the other stuff in that program?  Java has some objects in the
System class for interacting with a user.

  System.out is a PrintStream object that outputs to the screen.
  System.in is an InputStream object that reads from the keyboard.

Reminder:  this is shorthand for "System.in is a variable that references an
InputStream object."

But System.in doesn't have methods to read a line directly.  InputStream
objects (like System.in) read raw bytes from some source (like the keyboard),
but don't format the bytes.  InputStreamReader objects compose the raw bytes
into characters (which are typically two bytes long in Java).  BufferedReader
objects compose the characters into entire lines of text, and have a method
called "readLine" that reads and returns one.  Why are these tasks divided
among three different classes?  So that any one task can be reimplemented
(say, for improved efficiency) without changing the other two.

The first line, "import java.io.*;", is present because the InputStreamReader
and BufferedReader classes are defined in a standard Java library called
java.io .  To use the Java libraries, other than java.lang, you need to
"import" them.

You could figure all of this out by looking at the constructors in the online
Java libraries API--specifically, in the java.io library.  The online API is
linked from the class Web page, and will show you tons of methods you can use
to do a lot of work for you.

Nested Loops
------------
A loop is _nested_ if it's inside another loop.  Here's a nested loop that
computes the divisors of each number between 2 and 9 (except the trivial
divisors:  1 and the number itself).

    int i = 2;
    while (i <= 9) {
      int j = 2;
      while (j < i) {
        if (i % j == 0) {
          System.out.println(i + " is divisible by " + j);
        }
        j++;
      }
      i++;
    }

The output is:

    4 is divisible by 2
    6 is divisible by 2
    6 is divisible by 3
    8 is divisible by 2
    8 is divisible by 4
    9 is divisible by 3

Boolean operators
-----------------
We've seen the boolean operators in lab:  &&, called "and"; ||, called "or";
and !, called "not".  These operators compute boolean values from boolean
values, according to the following _truth_table_.

                  a    |    b    ||  a && b  |  a || b  |    !a
               ==================||==============================
                false  |  false  ||  false   |  false   |   true
                false  |   true  ||  false   |   true   |
                 true  |  false  ||  false   |   true   |  false
                 true  |   true  ||   true   |   true   |

These operators are handy in "if" and "while" statements.

  if (income > 7300 && income <= 29700) {
    taxrate = 0.15;
  }

It's important not to take the names "and" and "or" too literally.  For
example, in English we can say, "If your income is over $7,300 AND under
$29,700, your marginal tax rate is 15%."  But you can't write the analog in
Java:

  if (income > 7300 && <= 29700) {           /* Compile-time error! */

So don't think of && as a literal, English "and".  Instead, think of "&&"
(and "||") as a mathematical operation that takes two booleans and returns
a boolean.