Module 8: Loops


Objectives

 

By the end of this module, for simple HelloWorld-like programs, you will be able to:

 


An example

 

Consider the following program:

public class Mooooooo {
    public static void main (String[] argv)
    {
        printM();
        printO();
        printO();
        printO();
        printO();
        printO();
        printO();
        // ....yawn...
        printO();
        printO();
    }
    public static void printM() {
        System.out.println("*   *");
        System.out.println("** **");
        System.out.println("* * *");
        System.out.println("*   *");
        System.out.println("*   *");
    }
    public static void printO() {
        System.out.println("*****");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*****");
    }
}

What we would like is a way to organize repetition.

We will do this using a version of the while-loop:

public class Mooooooo {
    public static void main (String[] argv)
    {
        int i = 0;

        printM();
        while (i < 10) {
	    printO();
	    i++;
        }
    }
    public static void printM() {
        System.out.println("*   *");
        System.out.println("** **");
        System.out.println("* * *");
        System.out.println("*   *");
        System.out.println("*   *");
    }
    public static void printO() {
        System.out.println("*****");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*****");
    }
}
 

In-Class Exercise 1: Print out your own animal sound in the above fashion using a while-loop for some repetitive letter in the sound.
 

In-Class Exercise 2: What have we done in the class so far that might use repetition well?
 

Let's zoom in on the for-loop and dissect it:

 

In-Class Exercise 3: Write a method called void printNums(int n) that prints all numbers up to (but not including) n.
 

In-Class Exercise 4: In the same class, write a method called void printOdds(int n) that prints all odd numbers up to (but not including) n.
 

In-Class Exercise 5: Draw the control-flow diagram for the method in Exercise 4. What happens when control reaches the end of the while loop body?
 

In-Class Exercise 6: Write a method called void printReverseNums(int n) that prints all numbers starting from n, down to and including 0.
 

In-Class Exercise 7: Write a method called String replace(String s, char from, char to) that returns a String with each instance of character from with character to. Now you see how some of the String methods are implemented!

Hints: remember charAt(int) and that you can construct strings using the + operator.

 

In-Class Exercise 8: Write a method void printChar(char ch, int num) that prints the character ch, num times, all on the same line. For example, calling printChar('*', 5), will print:

      *****
  
 

In-Class Exercise 9: Write a method printTriangle(int height) to print a triangle. Your method should invoke the printChar method to print the *s. printTriangle(5) will print:

      *
      **
      ***
      ****
      *****
  
 

In-Class Exercise 10: Write a method printTriangleRight(int height) to print a right-aligned triangle. printTriangleRight(5) will print:

          *
         **
        ***
       ****
      *****
  

This seems like a common pattern:
 

	int i = 0;
        while(i < n) {
	    printO();
	    i++;
        }
    
 

for loops --
create a new keyword to make it easier to use loops of this structure

int i = 0;
while(i < n) {
    printO();
    i++;
}

        ==        

for(int i = 0 ; i < n ; i++) {
    printO();
}


public class Mooooooo {
    public static void main (String[] argv)
    {
        printM();
        for (int i = 0 ; i < 10 ; i++) {
	    printO();
        }
    }
    public static void printM() {
        System.out.println("*   *");
        System.out.println("** **");
        System.out.println("* * *");
        System.out.println("*   *");
        System.out.println("*   *");
    }
    public static void printO() {
        System.out.println("*****");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*   *");
        System.out.println("*****");
    }
}
 

Let's zoom in on the for-loop and dissect it:

 

More generally, for loops can be seen as:

for(expressionOne ; expressionTwo ; expressionThree) {
    loopBody;
}

Where
 


Printing the loop variable

 

Consider this example:

 

In-Class Exercise 2: Type, compile and execute the above program. Then, change the loop conditions so that the numbers 1 through 10 are printed. Also add a print statement after the for-loop, that prints anything.
 

Observe:

  • We are able to print out the for-loop variable i.

  • We see that the loop is executed five times.
           => Each time the variable i has increased its value.
 

Mental execution:

  • When execution first reaches the for-loop, the initialization condition is executed:

    • Say to yourself "i is set to 0".

  • Important: the initialization condition is not executed again, unless we somehow return to the statement preceding the for-loop.
    (We'll see later how this can happen.)

  • Next, we test the re-entry condition:

    • Here, you say to yourself "Is i less than 6?"
    • The answer is "yes", so we enter the loop-body and execute what's inside.

  • Execute (just once) what's inside the loop body:

    • In this case the value of i, which is now 0, gets printed out.

  • After the loop-body has executed, we apply the increment

    • Say to yourself "Now i has the value 1".

  • Next, we test the loop-entry condition:

    • Here, you say to yourself "Is i less than 6?"
    • It clearly is, so we enter the loop again.

  • Once again, we execute the loop body:

    • Because i has the value 1, this is what gets printed.

  • Once again, we apply the increment:

    • Say to yourself "Now i has the value 2".

  • Next, apply the entry condition ... and so on.

  • Finally, after the 5-th time through, i will get the value 6.

    • The re-entry condition now fails, and we exit the for-loop.

  • What "exit" means:

    • Execution continues to just after the for-loop.
    • In this program, we didn't have anything else, but we could have had:

    • In this case, you would print "MOO!" to the screen.

  • Another way to understand how it works:

  • The for-loop is one of several such strange and fascinating creatures (structures) we'll encounter in programming.
 


Variations

 

To explore for-loops further, we'll look at some variations of the basic for-loop:

  • First, we could have named our for-loop variable anything we like:
      	for (int count=0; count<6; count++) {
    	    printBigO ();
    	}
           
    • It's customary to use short variable names like i and j.

  • To go through a loop five times, any range of numbers will do:
      	for (int i=10; i<16; i++) {
    	    printBigO ();
    	}
           
    • Of course, this doesn't work for printing, unless we want to print values from 10 to 15.

  • Here's an example of using the <= operator:
      	for (int i=1; i<=5; i++) {
    	    printBigO ();
    	}
           
    • Treat <= as one symbol ("less than or equal to").
    • We do this because the keyboard doesn't have a symbol for .

  • Here are different ways of incrementing by 1:
      	for (int i=0; i<6 i=i+1) {
    	    printBigO ();
    	}
    
      	for (int i=0; i<6; i+=1) {    // Using the += operator.
    	    printBigO ();
    	}
           
    In-Class Exercise 3: Write a program to print out the odd numbers from 1 to 25. Use a single for-loop with the appropriate increment.
     

  • One can count down just as easily:
      	for (int i=5; i>0; i--) {
    	    System.out.println (i);
    	}
           
      Notice the decrement-by-one operator --.
    • Observe the entry-condition is "as long as i>0".
 

In-Class Exercise 4: Write a program to print out the odd numbers from 25 down to 1.
 


Nested for-loops

 

We'll start by writing a program to print a little number triangle like this:

  1
  22
  333
  4444

Notice: there's repetition across a row of numbers: a potential use of for-loops!

Here's the program, using for-loops:

Observe:

  • We've used System.out.print to avoid printing each number on a single line.

  • System.out.println() merely goes to the next line.
    (Or, ends the current line being printed.)
 

In-Class Exercise 5: Add a row for 5 (with five of them). Just for the heck of it, could one use a for-loop to achieve the printing of 1? That is, answer the question: can a for-loop be set up so that you go into it exactly once?
 

Next, observe that the upper-limits of the for-loops are themselves increasing:

Another way to say this:

    When the value is 2, print a row of 2's
    When the value is 3, print a row of 3's
    When the value is 4, print a row of 4's
  

Thus, we could try to do is:

    for (int j=2; j<=4; j++) {
        // Print a row of j's (j of them)
    }
  

But we already know how to print a row of j's:

    for (int j=2; j<=4; j++) {
        // Print a row of j's (j of them)
        for (int i=0; i<j; i++) {
            System.out.print (j)
        }
    }
  

The complete program:

 

In-Class Exercise 6: Change the program to print a fifth row with five 5's. Then include the row of 1's inside the loop: that is, fix the for-loop conditions so that you don't need the stand-alone println to print 1.
 

Let's point out a few more things about this example:

  • The outer loop variable's value is used in the inner loop:

  • Consider a single iteration of the outer-loop (e.g., when j is 3).

    • For this value of j, the inner loop executes j times.
    • Thus, when j is 3, the inner loop has 3 iterations.

  • This is an example of a nested for-loop in which the inner loop's execution depends on the value of the outer-loop variable.
 

In-Class Exercise 7: Trace through the execution for each possible value of j and i.
 

In-Class Exercise 8: Consider this program:

First, trace through the values of i and j by hand (using pen-and-paper) and try to figure out what gets printed. Do this painstakingly for each possible value of i and j. Then, edit, compile and execute the program to see if you were right.
 

In-Class Exercise 9: Write a program to print out consecutive integers in a diagonal, as in

  1
   2
    3
     4
      5
  
 


Reading and writing

 

Let's consider how to read a single for-loop, such as:

  • First, "see" the entire for-block as a whole, without looking at the details:

    Note: like the class but unlike methods, the opening brace is on the same line as the for.

  • Then, figure out how the for-loop variable is going to change:

    Say to yourself

    • "The variable is i and it starts at 0."
    • "The increment is 1."
    • "The last iteration is when i is 5."

  • Next, look for where the loop-variable is being used:

  • Now perform the mental execution, iteration by iteration.
           => It helps to write down successive values of loop variables.
 

Writing:

  • Make sure that you stick to the conventional style.

  • Again, when writing, always type matching brackets together.
 

In-Class Exercise 10: Consider the following program:

What does it print? Try to figure this out by mental execution first. Then, type it up, compile and execute to confirm.
 


When things go wrong

 

As code gets more complex, it gets easier to make mistakes, and harder to find them.
 

In-Class Exercise 11: In each of the programs below, try to determine the error without compiling the program. Then, write up the program, compile and see what the compiler says.

Program 1:

Program 2:

Program 3:

Program 4:

Program 5:

Program 6:

 

The last one is technically not a syntax error but a logical error:

  • Logical errors compile fine, but cause a problem during execution.

  • The process of identifying and fixing logical errors is called debugging.

  • A bug is a logical error.
 

In-Class Exercise 12: The following program is supposed to print the triangle of numbers:

1
22
333
4444
But there are two bugs. Type it in and see what the output really is. Can you find the problems by reading?