16.1. Selecting the Kind of Loop

 < Free Open Study > 

In most languages, you'll use a few kinds of loops:

  • The counted loop is performed a specific number of times, perhaps one time for each employee.

  • The continuously evaluated loop doesn't know ahead of time how many times it will be executed and tests whether it has finished on each iteration. For example, it runs while money remains, until the user selects quit, or until it encounters an error.

  • The endless loop executes forever once it has started. It's the kind you find in embedded systems such as pacemakers, microwave ovens, and cruise controls.

  • The iterator loop performs its action once for each element in a container class.

The kinds of loops are differentiated first by flexibility whether the loop executes a specified number of times or whether it tests for completion on each iteration.

The kinds of loops are also differentiated by the location of the test for completion. You can put the test at the beginning, the middle, or the end of the loop. This characteristic tells you whether the loop executes at least once. If the loop is tested at the beginning, its body isn't necessarily executed. If the loop is tested at the end, its body is executed at least once. If the loop is tested in the middle, the part of the loop that precedes the test is executed at least once, but the part of the loop that follows the test isn't necessarily executed at all.

Flexibility and the location of the test determine the kind of loop to choose as a control structure. Table 16-1 shows the kinds of loops in several languages and describes each loop's flexibility and test location.

Table 16-1. The Kinds of Loops

Language

Kind of Loop

Flexibility

Test Location

Visual Basic

For-Next

rigid

beginning

 

While-Wend

flexible

beginning

 

Do-Loop-While

flexible

beginning or end

 

For-Each

rigid

beginning

C, C++, C#, Java

for

flexible

beginning

 

while

flexible

beginning

 

do-while

flexible

end

 

foreach[*]

rigid

beginning


[*] Available only in C#. Planned for other languages, including Java, at the time of this writing.

When to Use a while Loop

Novice programmers sometimes think that a while loop is continuously evaluated and that it terminates the instant the while condition becomes false, regardless of which statement in the loop is being executed (Curtis et al. 1986). Although it's not quite that flexible, a while loop is a flexible loop choice. If you don't know ahead of time exactly how many times you'll want the loop to iterate, use a while loop. Contrary to what some novices think, the test for the loop exit is performed only once each time through the loop, and the main issue with respect to while loops is deciding whether to test at the beginning or the end of the loop.

Loop with Test at the Beginning

For a loop that tests at the beginning, you can use a while loop in C++, C#, Java, Visual Basic, and most other languages. You can emulate a while loop in other languages.

Loop with Test at the End

You might occasionally have a situation in which you want a flexible loop, but the loop needs to execute at least one time. In such a case, you can use a while loop that is tested at its end. You can use do-while in C++, C#, and Java, Do-Loop-While in Visual Basic, or you can emulate end-tested loops in other languages.

When to Use a Loop-With-Exit Loop

A loop-with-exit loop is a loop in which the exit condition appears in the middle of the loop rather than at the beginning or at the end. The loop-with-exit loop is available explicitly in Visual Basic, and you can emulate it with the structured constructs while and break in C++, C, and Java or with gotos in other languages.

Normal Loop-With-Exit Loops

A loop-with-exit loop usually consists of the loop beginning, the loop body (including an exit condition), and the loop end, as in this Visual Basic example:

Visual Basic Example of a Generic Loop-With-Exit Loop
 Do    ...       <-- 1    If ( some exit condition ) Then Exit Do    ...       <-- 2 Loop

(1)Statements.

(2)More statements.

The typical use of a loop-with-exit loop is for the case in which testing at the beginning or at the end of the loop requires coding a loop-and-a-half. Here's a C++ example of a case that warrants a loop-with-exit loop but doesn't use one:

C++ Example of Duplicated Code That Will Break Down Under Maintenance
 // Compute scores and ratings. score = 0; GetNextRating( &ratingIncrement );       <-- 1 rating = rating + ratingIncrement;       <-- 1 while ( ( score < targetScore ) && ( ratingIncrement != 0 ) ) {    GetNextScore( &scoreIncrement );    score = score + scoreIncrement;    GetNextRating( &ratingIncrement );       <-- 2    rating = rating + ratingIncrement;       <-- 2 }

(1)These lines appear here.

(2)…and are repeated here.

The two lines of code at the top of the example are repeated in the last two lines of code of the while loop. During modification, you can easily forget to keep the two sets of lines parallel. Another programmer modifying the code probably won't even realize that the two sets of lines are supposed to be modified in parallel. Either way, the result will be errors arising from incomplete modifications. Here's how you can rewrite the code more clearly:

C++ Example of a Loop-With-Exit Loop That's Easier to Maintain
 // Compute scores and ratings. The code uses an infinite loop // and a break statement to emulate a loop-with-exit loop. score = 0; while ( true ) {    GetNextRating( &ratingIncrement );    rating = rating + ratingIncrement;    if ( !( ( score < targetScore ) && ( ratingIncrement != 0 ) ) ) {       <-- 1       break;    }    GetNextScore( &scoreIncrement );    score = score + scoreIncrement; }

(1)This is the loop-exit condition (and now it could be simplified using DeMorgan's Theorems, described in Section 19.1).

Here's how the same code is written in Visual Basic:

Visual Basic Example of a Loop-With-Exit Loop
' Compute scores and ratings score = 0 Do    GetNextRating( ratingIncrement )    rating = rating + ratingIncrement    If ( not ( score < targetScore and ratingIncrement <> 0 ) ) Then Exit Do    GetNextScore( ScoreIncrement )    score = score + scoreIncrement Loop

Consider these finer points when you use this kind of loop:

Put all the exit conditions in one place. Spreading them around practically guarantees that one exit condition or another will be overlooked during debugging, modification, or testing.

Cross-Reference

Details on exit conditions are presented later in this chapter. For details on using comments with loops, see "Commenting Control Structures" in Section 32.5.


Use comments for clarification. If you use the loop-with-exit loop technique in a language that doesn't support it directly, use comments to make what you're doing clear.

The loop-with-exit loop is a one-entry, one-exit, structured control construct, and it is the preferred kind of loop control (Software Productivity Consortium 1989). It has been shown to be easier to understand than other kinds of loops. A study of student programmers compared this kind of loop with those that exited at either the top or the bottom (Soloway, Bonar, and Ehrlich 1983). Students scored 25 percent higher on a test of comprehension when loop-with-exit loops were used, and the authors of the study concluded that the loop-with-exit structure more closely models the way people think about iterative control than other loop structures do.


In common practice, the loop-with-exit loop isn't widely used yet. The jury is still locked in a smoky room arguing about whether it's a good practice for production code. Until the jury is in, the loop-with-exit loop is a good technique to have in your programmer's toolbox as long as you use it carefully.

Abnormal Loop-With-Exit Loops

Another kind of loop-with-exit loop that's used to avoid a loop-and-a-half is shown here:

C++ Example of Entering the Middle of a Loop with a goto---Bad Practice

goto Start; while ( expression ) {    // do something    ...    Start:    // do something else    ... }


At first glance, this seems to be similar to the previous loop-with-exit examples. It's used in simulations in which // do something doesn't need to be executed at the first pass through the loop but // do something else does. It's a one-in, one-out control construct: the only way into the loop is through the goto at the top, and the only way out of the loop is through the while test. This approach has two problems: it uses a goto, and it's unusual enough to be confusing.

In C++, you can accomplish the same effect without using a goto, as demonstrated in the following example. If the language you're using doesn't support a break command, you can emulate one with a goto.

C++ Example of Code Rewritten Without a goto Better Practice
 while ( true ) {    // do something else       <-- 1    ...    if ( !( expression ) ) {      break;    }    // do something    ... }

(1)The blocks before and after the break have been switched.

When to Use a for Loop

A for loop is a good choice when you need a loop that executes a specified number of times. You can use for in C++, C, Java, Visual Basic, and most other languages.

Further Reading

For more good guidelines on using for loops, see Writing Solid Code (Maguire 1993).


Use for loops for simple activities that don't require internal loop controls. Use them when the loop control involves simple increments or simple decrements, such as iterating through the elements in a container. The point of a for loop is that you set it up at the top of the loop and then forget about it. You don't have to do anything inside the loop to control it. If you have a condition under which execution has to jump out of a loop, use a while loop instead.

Likewise, don't explicitly change the index value of a for loop to force it to terminate. Use a while loop instead. The for loop is for simple uses. Most complicated looping tasks are better handled by a while loop.

When to Use a foreach Loop

The foreach loop or its equivalent (foreach in C#, For-Each in Visual Basic, for-in in Python) is useful for performing an operation on each member of an array or other container. It has the advantage of eliminating loop-housekeeping arithmetic and therefore eliminating any chance of errors in the loop-housekeeping arithmetic. Here's an example of this kind of loop:

C# Example of a foreach Loop
int [] fibonacciSequence = new int [] { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 }; int oddFibonacciNumbers = 0; int evenFibonacciNumbers = 0; // count the number of odd and even numbers in a Fibonacci sequence foreach ( int fibonacciNumber in fibonacciSequence ) {    if ( fibonacciNumber % 2 ) == 0 ) {       evenFibonacciNumbers++;    }    else {       oddFibonacciNumbers++;    } } Console.WriteLine( "Found {0} odd numbers and {1} even numbers.",    oddFibonacciNumbers, evenFibonacciNumbers );

 < Free Open Study > 


Code Complete
Code Complete: A Practical Handbook of Software Construction, Second Edition
ISBN: 0735619670
EAN: 2147483647
Year: 2003
Pages: 334

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net