CS 1073 Introductory Programming
for Scientific Applications
Repetition in Java


Overview:


Introduction to repetition (loops)

Loops have four sections

Three types of looping control in Java:


The while loop:

The while loop is the most commonly used kind of loop --- when in doubt, you can always use a while loop.

Form: while ( repetitionCondition )
                        loopBody

Interpretation: If repetitionCondition is true, the loopBody is executed and the repetitionCondition is reevaluated and tested. As long as the repetitionCondition is true the Loop Body is executed. As soon as repetitionCondition is false, the loop is terminated, and the statement after the loop is executed.

Example 1: Generate random integers between 0 and 5 (inclusive) until you get a 3. Output the number of values you drew.

   Random r = new Random();
   int numberValues = 0;
   while (r.nextInt(6) != 3){
      numberValues ++;
   }
   System.out.println("We had to draw " + (numberValues+1) + " values");
Why is does the last line use numberValues + 1?

The repetitionCondition in the while can be anything, but when the while loop is used for counting, the form will be:

                  //<== initialize counter
   while ( /* test whether the counter exceeded the limit? */ )   {
                     // <== stuff to repeat                    
                     // <== update the loop counter
   }

Example 2: Output the numbers between 1 and 10 using a while loop.

   int num = 1;
   while (num <= 10) {
      System.out.print( num + " ");
      num ++;
   }
   System.out.println();
The while repeats as long as the expression in the parenthesis evaluates to true and prints the following:

   1 2 3 4 5 6 7 8 9 10 
 


The for loop

The for loop is naturally designed for counting out a specific number.

Form: for( initialization; test; update )
                        loop-statement

Interpretation: The initialization is done first. Then the test is performed. If the test is true , execute the body of the loop. Then perform the update step and do the test again. As soon as the test is false , control passes to the statement after the for loop. (Draw a flow chart.)

Example 3: Print n asterisks on a line

   for (count = 0; count < n; count++)
      System.out.print("*");
   System.out.println();


The do - while loop

Form: do {
                        loop-body
              } while ( repetition-condition)

Interpretation: The loop-body is executed before the repetition-condition is tested. If the repetition-condition is true repeat the loop again.

Example 4: Write code to prompt the user to enter an integer greater than 0.

   int theNumber;
   do {
      System.out.println("Please enter an integer > 0");
      theNumber = Keyboard.readInt();
   } while (theNumber <= 0);
   System.out.println("The number you have entered is " + theNumber);


Fence post problems:

Fence post problems arise when the endpoints are treated differently than the other values.

Example 5: A straightforward approach to outputting the integers between 1 and 10 separated by commas has an extra comma on the end:

   int num = 1; 
   while ( num <= 10 ) { 
      System.out.print( num + ","); 
      num ++; 
} System.out.println();

The output for this code is: 1,2,3,4,5,6,7,8,9,10, note the trailing comma!

The problem here is that the number of numbers is one more than the number of commas

   |~~~|~~~|~~~|~~~| 
|~~~|~~~|~~~|~~~|
There are three alternatives:

Alternative 1: Print the first fence post (number) before the loop:

   int num = 1;
   System.out.print(num);      
   num++;                       
   while ( num <= 10 ) {                           
      System.out.print("," + num); 
      num++;                      
   }
   System.out.println();

Alternative 2: Print the last post(number) after the loop:
   int num = 1;
   while ( num < 10 ) {
      System.out.print(num + ",");
      num ++;
   }  
   System.out.println(num);

Alternative 3: Guard the printing of the crosspiece inside the loop:
   int num = 1; 
   while( num <= 10) {
      System.out.print(num); 
      if ( num < 10 ) 
        System.out.print(",");
      num++; 
   }
   System.out.println(); 


Flow of control:

Draw a schematic of the flow of control through the program.

Example 6: The inner loop is executed completely on each iteration of the outer loop.

   for (int j = 1; j <= 3; j++) {
      for (int k = 1; k <= 2; k++) {
         System.out.println(j + "," + k);
      }
    } 
Output:
   1,1
   1,2
   2,1
   2,2
   3,1
   3,2 

Example 7: The test of the inner loop can depend on the outer loop variable.

   for (int j = 1; j <= 5; j++) { 
      for (int k = 1; k <= j; k++) { 
         System.out.print( (j *k) + " "   ); 
      } 
      System.out.println(); 
   } 
Output:
   1 
   2  4 
   3  6  9 
   4  8 12 16 
   5 10 15 20 25 
Avoid nested loops if you can. Nested loops can often be eliminated by replacing the inner loop by an appropriate method call (resulting in a simpler, clearer, more general design).

Example 8: The following code produces a triangular design with numberLines rows.
   int line;  
   int i; 
   int numberStars = 1;   // number of stars to print on line
   for (line = 1; line <= numberLines; line++) {
           // Print the leading blanks
      for (i = 1; i <= numberLines - line; i++)         
         System.out.print(' ');
               // Print the stars
      for (i = 1; i <= numberStars; i++)
         System.out.print('*');
      System.out.println();
      numberStars += 2;  // add 2 to numberStars
   }
The inner loops are used to print out a certain number of asterisks after a certain number of blanks. We can replace this with a method:
   public static void printChars(int numBlanks, int numChars) {
      int i;
      for (i = 1; i <= numBlanks; i++) 
         System.out.print(' ');
           // Print the stars
      for (i = 1; i <= numChars; i++)
         System.out.print('*'); 
      System.out.println();
   }
The outer loop then becomes:
   int line;  
   int numberStars = 1;   // number of stars to print on line
   for (line = 1; line <= numberLines; line++) {    
       printChars(numberLines-line, numberStars);
       numberStars += 2;  // add 2 to numberStars 
   }  
This is much clearer and you can debug the printChars separately.

Question 1: How would you modify printChars to print any character rather than specifically asterisks?

Ans: Pass the character to be printed as an additional parameter.

Question 2: How could you use printChars to print other kinds of patterns? Ans: Instead of putting printChars in a loop, put explicit calls to printChars needed to form the pattern.


Miscellaneous loop comments:

Priming a loop: Reading an initial value or performing other kinds of initialization so that the loop test can be evaluated the first time is called priming the loop.

   int sum = 0;
System.out.println("Enter a number ");
int number = Keyboard.readInt();
while ( number != 0 ) {
sum += number;
System.out.println("Enter a number ");
number = Keyboard.readInt();
}
System.out.println("total = " + sum);

Review of loop problems and how to fix them:


Scope of an identifier

The scope of an identifier refers to the area of the program in which the item named by the identifier can be used. Variables and methods have scope. If you use an identifier outside of its scope, you will get an "undefined identifier" message.

   public static void main(String args[]) {
      int k = 1;
      while( k < 5 ){
         int ct = 0;
         System.out.println(k);
         k++;
      }
      System.out.println(k);
      //System.out.println(ct);  //ct NOT accessible here
      for (k = 1; k < 5; k++) {
         for (int j = 1; j < 5; j++) {
             System.out.println(k + "  " + j);
         }
         System.out.println(k);
         //System.out.println(j); // j NOT accessible here 
      }
      System.out.println(k); // k IS accessible here
   }
As an exercise, look at several of your programs and identify the scopes of the various identifiers.