Java Programming   Java Programming
 |Sofia Home | Content Gallery |
Home
Syllabus
Schedule
Lessons
Assignments
Resources

Lesson 6.2 Counted Loops

The first loop we're going to look at is the for loop. Both Pascal and Basic have for loops, as do C and C++. Like those languages, the for loop in Java is designed for writing counted loops--loops that repeat a specified number of times.

Unlike the Pascal or Basic for loop, however, the for loop in Java can do much more than simple counted loops. The for loop in Java works almost exactly like the for loop in C++; it is a general purpose, "test at the top" loop, that makes writing counted loops very straightforward, but can be used for other purposes.

Syntax

As mentioned previously, the body of the for loop follows the loop's test condition; you test first, then, if the test evaluates to true, you enter the loop body, as you can see in the illustration. [click image to enlarge]

Image illustrates the for loop syntax.

The for loop's condition involves more than a simple boolean test, however. In fact, it involves three different expressions:

  • The initialization expression
  • The test expression
  • The update expression
Each of these three expressions is separated from the others by a semicolon. You can omit any--or all--of the expressions, but the semicolons are required. [Make sure that you don't accidentally use commas instead of semicolons. When you do so, the javac compiler is not particularly helpful with its error messages]

The loop body following the loop condition is usually enclosed in braces, although, technically, braces are not required if the loop body consists of a single statement. As a practical matter, though, you'll almost always use braces, and, since they don't hurt--even when not strictly required--you should always put them in as a matter of course.

Let's return to the for loop condition, and take a closer look at each of its three expressions.

Back to Top

The Initialization Expression

When a for loop is encountered, the first part of the loop condition, the initialization expression, is executed. It is always executed, regardless of the other parts of the for statement, almost as if it occurred on the previous line.

The initialization expression is evaluated only once, and is usually used to define the counter variable that will control your loop, like this:
The for Loop Initialization Expression
for (int counter = 0; ... ; ...)
{
   // Can use counter here
}
// Cannot use counter here

Variables declared inside the for loop initialization section, like counter, shown here, are local to the body of the for loop. Once the loop is finished, the variable goes out of scope and can no longer be used.

The boolean Test

The second section of the for loop is called the test condition. The test condition is a boolean expression which is evaluated immediately after the initialization expression. 

If the test condition is true, [when it is evaluated], then execution begins with the first statement in the loop. If it is false, then the entire loop body is skipped, and execution continues at the first statement following the loop body.

To continue our example, we can test the value of counter, checking to make sure it is less than ten:

The for Loop Test Expression
for (int counter = 0; 
    counter < 10 ; ...)
{
   // Can use counter here
}
// Cannot use counter here

Using counter like this insures that the loop will execute ten times. This is a common idiom in Java programming:

  • start counter at 0
  • test that counter is less than the upper bounds

An idiom is just a common and widely accepted way of "phrasing" a particular operation. This particular idiom works well, because you can immediately tell how many times the loop will execute just by glancing at the test condition.

Back to Top

The Update Expression

In Lesson 6.1, "Introduction to Loops", you learned to make sure that every repetition of a loop moves closer to the loop bounds. But, in the for loop shown here, there are no statements that move toward the bounds; in fact, as written, this example is an endless loop! Since counter is never updated, it always remains at zero.

Updating the counter is the responsibility of the third part of the for loop condition--the update expression. The update expression is evaluated after the body of the loop is finished, but before the test expression is evaluated for the next repetition. 

For a counted loop, you'll use the test expression to update your counter like this:
The for Loop Update Expression
for (int counter = 0; 
     counter < 10 ; 
     ++counter)
{
   // Can use counter here
}
// Cannot use counter here

Counting Variations

You've probably noticed that this loop doesn't really do anything; the portion that we've written simply repeats ten times. However, you can use this basic skeleton for any loop that needs to repeat a fixed number of times. Simply replace 10 with the number of times you want to repeat, and you're all set.

In addition to acting as a loop control, you can also use your counter variable to process different pieces of information during each repetition of the loop. Here, for instance, is a loop that sums the Unicode values for all the characters in a String:
Using the for Loop
String s = myTF.getText();
int nChars = s.length();
int sumOfCodes = 0;

for (int counter= 0; counter < nChars ; ++counter)
{
   sumOfCodes += s.charAt(counter);
}

myTF.setText("Sum of codes = " + sumOfCodes);

How much is your name worth? Type your name into the text area shown below, and press ENTER. The applet shown here [SumOfCodes.java] will total up the Unicode values for each of the characters in your name, and display your "weight" in Unicode.


Back to Top

Counting Down

When you create a counted loop using for, you are responsible for initializing the counter in the intitialization expression, and for updating it in the update expression. There's no law that says you have to start at zero, and there's nothing to stop you from counting down rather than up.

Here's a fragment that displays the characters in a String in reverse order. It works by walking through the characters of the String from the end to the beginning, using a for loop to count down, instead of counting up.
Counting Down With the for Loop
String s = myTF.getText();
int nChars = s.length();
String output = "";

for (int counter = nChars - 1; 
     counter >= 0 ; 
     --counter)
{
   output += s.charAt(counter);
}

outputLbl.setText(output);

Type in a phrase, press ENTER, and the applet shown here [ReverseString.java] will reverse it, thanks to the magic of the for loop.

 

What's with the -1?
You might wonder why the code shown here subtracts one from the length of the String in the initialization expression. In a String, the characters are numbered starting with zero. Thus, if there are 10 characters in a particular String, then the last character is in position 9.
Shows that individual characters in a String are numbered starting at 0. [Click to enlarge]
Back to Top

Counting by Steps

Not only can you count up and count down, you can also count by values other than 1 simply by changing the value in the update expression. The Basic language allows you do do this via its STEP clause, but the Java for loop allows you to use any expression you like, not just different constant values.

Here, for instance, is how you could calculate the sum of all the even numbers less than 100:

Sum = 0;
for (int i = 0; i < 100; i += 2)
{
  Sum += i;
}

And, here's a loop that displays exponential growth. How many numbers do you think that this will print?

for (int i = 2; i < 10000; i *= i)
{
  System.out.println(i);
}
Back to Top

Counted Loops with while

The for loop makes writing counted loops very easy because it puts the pieces you need--a place to initialize your counter, a place to test your counter, and a place to update your counter--all within easy reach. 

You can do exactly the same thing with Java's simpler, but more general-purpose while loop. It's just not quite as convenient.

Syntax

Image illustrates the syntax of the while loop.

The while loop, which you can see in the illustration [click to expand], only has three parts:

  • the keyword while
  • a boolean test
  • the loop body

To use the while statement to build a counted loop, you must do three things:

  1. Create a counter variable, and initialize it before the loop starts. This takes the place of the initialization expression in the for loop.
  2. Test the counter variable inside the while condition.
  3. Update your counter at the end of the loop body. This takes the place of the update expression in the for loop.

Here's the basic skeleton for a counted loop, written with while:

A Counted Loop Skeleton with while
int counter = 0;
while ( counter < 10 )
{
   // Loop body statements

   // Update loop counter
   counter++;
}

Caveats

There are three common errors that often occur when writing counted loops using while. By learning what they are, and then checking for each one when you write your loops, you increase your chances of writing a correct loop the first time.

Expired Counters

When using the for loop, you usually create and initialize your counter variables inside the initialization expression of the for loop. If you forget to do so, the for loop condition usually looks "empty", which acts as a reminder.

For the while loop, however, you must define and initialize your counter outside the while loop. This has several implications:

  • In the for loop, the scope of the counter variable is restricted to the body of the for loop. That is not true for the while loop.
  • If you have several while loops, and each of them use the same variable name, then you cannot redeclare the variable for each new loop. All of your loops will use the same variable.
  • You must, however, remember to reinitialize the counter before each loop, even though you can't redeclare it. Forgetting to do this often leads to the case of the expired counter. If a counted while loop is preceded by another, and both use the same counter variable, you may forget to reinitialize the counter for the second loop. This doesn't create a syntax error, but it does give you the wrong answer.
There are two possible solutions to the expired counter problem. 
  1. If you give all of your counters unique names, you won't run into the problem. Sometimes, however, this is hard to do. Thinking up a new name when you really want to use the common counter names like i, idx, or counter, can be difficult.
  2. A better solution is to train yourself to always initialize your counter on the line immediately preceeding the while condition. After a bit, a missing initialization starts to look as "empty" as the missing initialization section in a for loop.
Back to Top

Endless Loops

The problem of endless loops is not unique to while loops. You can create endless loops in a variety of ways. [For instance, if you change the bounds of the exponential for loop shown at the end of the previous section to 100000 from 10000, it will become an endless loop. Can you tell why?] 

A counted while loop lends itself to endless loops in a way that the others don't. Because the while loop places the counter update expression at the bottom of the loop--which may be far removed from the while loop condition by the time all of the intervening statements have been added--it is easy to forget it.

With the for loop, leaving out the update expression creates an "empty" looking loop condition, but not with the while loop.

The easiest solution to this problem is to use the loop-building strategy presented in Lesson 6.1, "Introduction to Loops". If you start by first writing the "mechanics" of the loop--bounds, precondition, and update--you are less likely to get distracted by the "real" statements and forget to add the update expression at the end of the loop.

Back to Top

Phantom Semicolon

This last problem is also not restricted to while loops; it affects selection statements and for loops as well.

If you put a semicolon after the condition of a while [or for] loop, the body of the loop becomes the null statement. Here's an example:

while (cups < 10);

   // Can NEVER get here if cups is < 10
}

Because of the semicolon, you are saying 

"As long as cups is less than ten, do nothing".
This creates two problems:
  1. If cups was originally less than ten, you will have an endless loop. Because nothing in the null body changes the value of cups, it will remain at its intial value.
  2. If cups was greater-than or equal-to ten, you will not have an endless loop, but the statements that were intended to be executed as part of the loop body will be executed exactly once.
Back to Top

Where To Now?

After reading the preceding section, you might be wondering why anyone would bother with while at all. The for loop seems so much more capable. 

That's true for counted loops; if you are going to write loops that are controlled by a counter, you should probably use the for loop. But, not all loops, or even most loops, are counter-controlled. Event controlled loops are much more common, and there, the while loop reigns.

Once you've finished the Something to Talk About exercise, you can turn your attention to the next lesson, "Indefinite Loops".

Something to Talk About

Here's something to try out. Download, compile and run ReverseString.java. Change the program so that it prints out the original String in forward--not reverse--order, but only displays every other character. 

What does your loop look like?

Please continue to the next section of this lesson.

 

Back to Top

 

Content Developed by Stephen Gilbert, Licensed under a Creative Commons License
Published by the Sofia Open Content Initiative
© 2004 Foothill-De Anza Community College District &The William and Flora Hewlett Foundation