Section 5.3. Iteration (Looping) Statements


5.3. Iteration (Looping) Statements

There are many situations in which you will want to do the same thing again and again, perhaps slightly changing a value each time you repeat the action. This is called iteration , or looping . Typically, you'll iterate (or loop) over a set of items, taking the same action on each item in the collection. This is the programming equivalent of an assembly line. On an assembly line, you might take a hundred car bodies and put a windshield on each one as it comes by. In an iterative program, you might work your way through a collection of text boxes on a form, retrieving the value from each in turn and using those values to update a database.

C# provides an extensive suite of iteration statements, including for and while , and also do...while and foreach loops . You can also create a loop by using the goto statement. The remainder of this chapter considers the use of goto , for , while , and do...while . However, we'll postpone coverage of foreach until Chapter 10.

5.3.1. Creating Loops with goto

The goto statement was used earlier in this chapter as an unconditional branch in a switch statement. The more common use of goto , however, is to create a loop. In fact, the goto statement is the seed from which all other looping statements have been germinated. Unfortunately, it is a semolina seed, producer of "spaghetti code" (see the following sidebar) and endless confusion.

Spaghetti Code

Goto can cause your method to loop back and forth in ways that are difficult to follow. If you were to try to draw the flow of control in a program that makes extensive use of goto statements, the resulting morass of intersecting and overlapping lines might look like a plate of spaghetti hence the term "spaghetti code ."

Spaghetti code is a contemptuous epithet; no one wants to write spaghetti code, and so most experienced programmers avoid using goto to create loops.


Because of the problems created by the goto statement, it is rarely used in C# outside of switch statements, but in the interest of completeness, here's how you create goto loops:

  1. Create a label.

  2. goto that label.

The label is an identifier followed by a colon . You place the label in your code, and then you use the goto keyword to jump to that label. The goto command is typically tied to an if statement, as illustrated in Example 5-11.

Example 5-11. Using goto
 using System; public class Tester {    public static void Main(  )    {       int counterVariable = 0;    repeat: // the label       Console.WriteLine(       "counterVariable: {0}", counterVariable );       // increment the counter       counterVariable++;       if ( counterVariable < 10 )          goto repeat; // the dastardly deed    } } 

The output looks like this:

 counterVariable: 0     counterVariable: 1     counterVariable: 2     counterVariable: 3     counterVariable: 4     counterVariable: 5     counterVariable: 6     counterVariable: 7     counterVariable: 8     counterVariable: 9 

This code is not terribly complex; you've used only a single goto statement. However, with multiple such statements and labels scattered through your code, tracing the flow of execution becomes very difficult.

It was the phenomenon of spaghetti code that led to the creation of alternatives, such as the while loop.

5.3.2. The while Loop

The semantics of the while loop are "while this condition is true, do this work." The syntax is:

 while (   Boolean expression   )   statement   

As usual, a Boolean expression is any statement that evaluates to true or false. The statement executed within a while statement can of course be a block of statements within braces. Example 5-12 illustrates the use of the while loop.

Example 5-12. The while loop
 using System; public class Tester {    public static void Main(  )    {       int counterVariable = 0;       // while the counter variable is less than 10       // print out its value       while ( counterVariable < 10 )       {          Console.WriteLine( "counterVariable: {0}", counterVariable );          counterVariable++;       }    } } 

The output looks like this:

 counterVariable: 0     counterVariable: 1     counterVariable: 2     counterVariable: 3     counterVariable: 4     counterVariable: 5     counterVariable: 6     counterVariable: 7     counterVariable: 8     counterVariable: 9 

The code in Example 5-12 produces results identical to the code in Example 5-11, but the logic is a bit more clear. The while statement is nicely self-contained, and it reads like an English sentence : "while counterVariable is less than 10, print this message and increment counterVariable ."

Notice that the while loop tests the value of counterVariable before entering the loop. This ensures that the loop will not run if the condition tested is false. Thus, if counterVariable is initialized to 11, the loop will never run.

5.3.3. The do ... while Loop

There are times when a while loop might not serve your purpose. In certain situations, you might want to reverse the semantics from "run while this is true" to the subtly different "do this, while this condition remains true." In other words, take the action, and then, after the action is completed, check the condition. Such a loop will always run at least once.

To ensure that the action is taken before the condition is tested, use a do...while loop:

 do   statement   while (   boolean-expression   ); 

The syntax is to write the keyword do , followed by your statement (or block), the while keyword, and the condition to test in parentheses. End the statement with a semicolon.

Example 5-13 rewrites Example 5-12 to use a do...while loop.

Example 5-13. The do...while loop
 using System; public class Tester {    public static void Main(  )    {       int counterVariable = 11;       // display the message and then test that the value is       // less than 10       do       {          Console.WriteLine( "counterVariable: {0}", counterVariable );          counterVariable++;       } while ( counterVariable < 10 );    } } 

The output looks like this:

 counterVariable: 11 

In Example 5-13, counterVariable is initialized to 11 and the while test fails, but only after the body of the loop has run once.

5.3.4. The for Loop

A careful examination of the while loop in Example 5-12 reveals a pattern often seen in iterative statements: initialize a variable ( counterVariable=0 ), test the variable ( counterVariable<10 ), execute a series of statements, and increment the variable ( counterVariable++ ). The for loop allows you to combine all these steps in a single statement. You write a for loop with the keyword for , followed by the for header, using the syntax:

 for ([   initializers   ]; [   expression   ]; [   iterators   ])   statement   

The first part of the header is the initializer , in which you initialize a variable. The second part is the Boolean expression to test. The third part is the iterator , in which you update the value of the counter variable. All of this is enclosed in parentheses.

A simple for loop is shown in Example 5-14.

Example 5-14. A for loop
 using System; public class Tester {    public static void Main(  )    {       for ( int counter = 0; counter < 10; counter++ )       {          Console.WriteLine(          "counter: {0} ", counter );       }    } } 

The output looks like this:

 counter: 0     counter: 1     counter: 2     counter: 3     counter: 4     counter: 5     counter: 6     counter: 7     counter: 8     counter: 9 

The counter variable is initialized to zero in the initializer:

 for (  int counter=0  ; counter<10; counter++) 

The value of counter is tested in the expression part of the header:

 for (int counter=0;  counter<10  ; counter++) 

Finally, the value of counter is incremented in the iterator part of the header:

 for (int counter=0; counter<10;  counter++  ) 

The initialization part runs only once, when the for loop begins. The integer value counter is created and initialized to zero, and the test is then executed. Because counter is less than 10, the body of the for loop runs and the value is displayed.

After the loop completes, the iterator part of the header runs and counter is incremented. The value of the counter is tested, and, if the test evaluates true, the body of the for statement is executed again.

Your iterator doesn't just have to be ++ . You can use, or any other expression that changes the value of the counter variable, as the needs of your program dictate . Also, for the purposes of a for loop, counter++ and ++counter will have the same result.


The logic of the for loop is as if you said, "For every value of counter that I initialize to zero, take this action if the test returns true, and after the action, update the value of counter."

5.3.4.1. Controlling a for loop with the modulus operator

The modulus operator really comes into its own in controlling for loops. When you perform modulus n on a number that is a multiple of n , the result is zero. Thus, 80%10=0 because 80 is an even multiple of 10. This fact allows you to set up loops in which you take an action every n th time through the loop by testing a counter to see whether %n is equal to zero, as illustrated in Example 5-15.

Example 5-15. Using modulus to find the tenth iteration
 using System; public class Tester {    public static void Main(  )    {       for ( int counter = 1; counter <= 100; counter++ )       {          Console.Write( "{0} ", counter );          if ( counter % 10 == 0 )          {             Console.WriteLine( "\t{0}", counter );          }     // end if       }        // end for    }           // end Main }              // end namespace 

The output looks like this:

 1 2 3 4 5 6 7 8 9 10    10     11 12 13 14 15 16 17 18 19 20    20     21 22 23 24 25 26 27 28 29 30    30     31 32 33 34 35 36 37 38 39 40    40     41 42 43 44 45 46 47 48 49 50    50     51 52 53 54 55 56 57 58 59 60    60     61 62 63 64 65 66 67 68 69 70    70     71 72 73 74 75 76 77 78 79 80    80     81 82 83 84 85 86 87 88 89 90    90     91 92 93 94 95 96 97 98 99 100   100 

In Example 5-15, the value of the counter variable is incremented each time through the loop. Within the loop, the value of counter is compared with the result of modulus 10 ( counter % 10 ). When this evaluates to zero, the value of counter is evenly divisible by 10, and the value is printed in the righthand column.

5.3.4.2. Breaking out of a for loop

It is possible to exit from a for loop even before the test condition has been fulfilled. To end a for loop prematurely, use the unconditional branching statement break .

The break statement halts the for loop, and execution resumes after the for loop statement (or closing brace ), as in Example 5-16.

Example 5-16. Using break to exit a for loop
 using System; public class Tester {    public static void Main(  )    {       for ( int counter = 0; counter < 10; counter++ )       {          Console.WriteLine(          "counter: {0} ", counter );          // if condition is met, break out.          if ( counter == 5 )          {             {                Console.WriteLine( "Breaking out of the loop" );                break;             }          }          Console.WriteLine( "For loop ended" );       }    } } 

The output looks like this:

 counter: 0     counter: 1     counter: 2     counter: 3     counter: 4     counter: 5     Breaking out of the loop     For loop ended 

In this for loop, you test whether the value counter is equal to 5. If that value is found (and in this case, it always will be), you break out of the loop.

5.3.4.3. The continue statement

Rather than breaking out of a loop, you may at times want the semantics of saying, "Don't execute any more statements in this loop, but start the loop again from the top of the next iteration." To accomplish this, use the unconditional branching statement continue .

Break and continue create multiple exit points and make for hard-to-understand, and thus hard-to-maintain, code. Use them with care.


Example 5-17 illustrates the mechanics of both continue and break . This code, suggested to me by one of my technical reviewers, Donald Xie, is intended to create a traffic signal processing system.

Example 5-17. Break and continue
 using System; public class Tester {    public static int Main(  )    {       string signal = "0"; // initialize to neutral       while ( signal != "X" ) // X indicates stop       {          Console.Write( "Enter a signal. X = stop. A = Abort: " );          signal = Console.ReadLine(  );          // do some work here, no matter what signal you          // receive          Console.WriteLine( "Received: {0}", signal );          if ( signal == "A" )          {             // faulty - abort signal processing             // Log the problem and abort.             Console.WriteLine( "Fault! Abort\n" );             break;          }          if ( signal == "0" )          {             // normal traffic condition             // log and continue on             Console.WriteLine( "All is well.\n" );             continue;          }          // Problem. Take action and then log the problem          // and then continue on          Console.WriteLine( "{0} -- raise alarm!\n", signal );       }       return 0;    } } 

The signals are simulated by entering numerals and uppercase characters from the keyboard, using the Console.ReadLine( ) method, which reads a line of text from the keyboard. ReadLine( ) reads a line of text into a string variable. The string ends when you press A.

The algorithm is simple: receipt of a "0" (zero) means normal conditions, and no further action is required except to log the event. (In this case, the program simply writes a message to the console; a real application might enter a time-stamped record in a database.)

On receipt of an Abort signal (simulated with an uppercase "A"), the problem is logged and the process is ended. Finally, for any other event, an alarm is raised, perhaps notifying the police. (Note that this sample does not actually notify the police, though it does print out a harrowing message to the console.) If the signal is "X," the alarm is raised but the while loop is also terminated .

Here's one sample output:

 Enter a signal. X = stop. A = Abort: 0     Received: 0     All is well.     Enter a signal. X = stop. A = Abort: 1     Received: 1     1 -- raise alarm!     Enter a signal. X = stop. A = Abort: X     Received: X     X -- raise alarm! 

Here's a second sample output:

 Enter a signal. X = stop. A = Abort: A     Received: A     Fault! Abort 

The point of this exercise is that when the A signal is received, the action in the if statement is taken and then the program breaks out of the loop, without raising the alarm. When the signal is 0, it is also undesirable to raise the alarm, so the program continues from the top of the loop.

Be sure to use uppercase letters for X and A. To keep the code simple, there is no code to check for lowercase letters or other inappropriate input.


5.3.4.4. Optional for loop header elements

You will remember that the for loop header has three partsinitialization, expression, and iterationand the syntax is as follows :

 for ([   initializers   ]; [   expression   ]; [   iterators   ])   statement   

Each part of the for loop header is optional. You can, for example, initialize the value outside the for loop, as shown in Example 5-18.

Example 5-18. No initialization with for loop
 using System; public class Tester {    public static void Main(  )    {       int counter = 0;       // some work here       counter = 3;       // more work here       for ( ; counter < 10; counter++ )       {          Console.WriteLine(          "counter: {0} ", counter );       }    } } 

The output looks like this:

 counter: 3     counter: 4     counter: 5     counter: 6     counter: 7     counter: 8     counter: 9 

In this example, the counter variable was initialized and modified before the for loop began . Notice that a semicolon is used to hold the place of the missing initialization statement.

You can also leave out the iteration step if you have reason to increment the counter variable inside the loop, as shown in Example 5-19.

Example 5-19. Leaving out the iterator step
 using System; public class Tester {    public static void Main(  )    {       for ( int counter = 0; counter < 10; ) // no increment       {          Console.WriteLine(          "counter: {0} ", counter );          // do more work here          counter++; // increment counter       }    } } 

You can mix and match which statements you leave out of a for loop.

If you create a for loop with no initializer or incrementer, like this:

 for  ( ; counter < 10 ; ) 

you have a while loop in for loop's clothing; and of course that construct is silly, and thus not used very often.


It is even possible to leave all the statements out, creating what is known as a forever loop:

 for ( ;; ) 

You can create the exact same effect with a while(true) loop

 while ( true ) 


You break out of a forever (or while(true) ) loop with a break statement. A forever loop is shown in Example 5-20.

Example 5-20. A forever loop
 using System; public class Tester {    public static void Main(  )    {       int counterVariable = 0; // initialization       for ( ; ; )  // forever       {          Console.WriteLine(          "counter: {0} ", counterVariable++ ); // increment          if ( counterVariable > 10 ) // test             break;       }    } } 

The output looks like this:

 counter: 0     counter: 1     counter: 2     counter: 3     counter: 4     counter: 5     counter: 6     counter: 7     counter: 8     counter: 9     counter: 10 

Use a forever loop to indicate that the "normal" case is to continue the loop indefinitely; for example, if your program is waiting for an event to occur somewhere in the system. The conditions for breaking out of the loop would then be exceptional and managed inside the body of the loop.

Although it is possible to use a forever loop to good effect, Example 5-20 is a degenerate case. The initialization, increment, and test would be done more cleanly in the header of the for loop, and the program would then be easier to understand. It is shown here to illustrate that a forever loop is possible.

5.3.4.5. The while (true) construct

You can accomplish exactly the same semantics of a forever loop using the while (true) construct, as shown in Example 5-21.

Example 5-21. The while (true) construct
 using System; public class Tester {    public static void Main(  )    {       int counterVariable = 0; // initialization       while ( true )       {          Console.WriteLine(          "counter: {0} ", counterVariable++ ); // increment          if ( counterVariable > 10 ) // test             break;       }    } } 

The output looks like this:

 counter: 0     counter: 1     counter: 2     counter: 3     counter: 4     counter: 5     counter: 6     counter: 7     counter: 8     counter: 9     counter: 10 

Example 5-21 is identical to Example 5-20, except that the forever construct:

 for ( ;; ) 

is replaced with a:

 while (true) 

statement. Of course, the keyword true always returns the Boolean value true; so like the forever loop, this while loop runs until the break statement is executed.



Learning C# 2005
Learning C# 2005: Get Started with C# 2.0 and .NET Programming (2nd Edition)
ISBN: 0596102097
EAN: 2147483647
Year: 2004
Pages: 250

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