Iteration (Looping)
AAHC

Click on A to make all fonts on the page smaller.

Click on A to make all fonts on the page larger.

Click on HC to toggle high contrast mode. When you move your mouse over some bold words in high contrast mode, related words are automatically highlighted. Text is shown in black and white.


In this lesson, we will cover iterations, or looping—another topic we've sprinkled into our lessons so far. The iteration statements in C# are for, while, and do..while. There is also a foreach statement using the in keyword that is used to iterate over elements within an array or collection object. We'll discuss this iteration technique later, when we discuss arrays.

The For Loop

The for loop is used to repeat one or more statements until a specific expression evaluates to false. The statements within a for loop may not execute if the expression evaluates to false initially. The format and components (note that all of the components are optional) are:

For Loop Syntax:
for (declaration and initialization ; condition ; iteration )
        

The declaration and initialization component of the for loop may be used to declare one or more variables. Good programming practices would recommend using the declaration and initialization component to declare and initialize a variable that would be used to establish the iteration, as we'll see shortly. However, you can declare variables before starting a for loop if you want to access the value of such variables after the loop concludes. Variables declared within the declaration and initialization section are not available after the loop concludes. Note that we used the plural—variables. You may declare and initialize multiple variables, separated by commas. Here are a few examples of declarations and initializations:

The condition component of the for loop may be used to evaluate an expression to determine the number of iterations of the loop. The condition component may use any combination of boolean, relational, and logical operators. Here are a few examples of conditions:

If you omit the condition component, you must provide an alternative method to exit the loop, or you will be create an infinite loop. Even with the condition, you must provide a way to exit the loop, typically by adjusting the variables of the condition component in the iteration component.

The iteration component of the for loop may be used to adjust one or more variables usually used to control the number of times loop is repeated. If you do not adjust the variables within the iteration section, you must provide a way to adjust those variables to prevent creating an infinite loop. Here are a few examples of iterations.

The While Loop

The while loop is used to repeat one or more statements repeatedly until a specific expression evaluates to false. The statements within a while loop may never execute if the expression evaluates to false initially. The format of the while loop is:

While Loop Syntax
while (condition)
        

The condition expression of the while loop consists of an expression normally used to determine how many times to iterate through the loop. Within the loop block, variables contained within the condition expression are modified to ensure that the loop eventually concludes to prevent an infinite loop condition. Just as with the for loop, you may use any combination of boolean, relational, and logical operators. Here are a few examples:

The Do..While Loop

The do..while loop (often referred to as just a do loop) repeats one or more statements until a specific condition evaluates to false. The statements in a do..while loop must execute at least once, because the evaluation expression follows the statements. Below is the format of the do..while loop:

Do..While Loop Syntax
do
while (condition)
        

The structure of the do..while indicates that all statements following the do component will execute before the condition is evaluated. Whenever you need a loop that must execute at least once, use the do..while mechanism. For examples, see the while loop above.

For Loop Versus While Loop

So, when do you use a for loop, and when do you use a while or do..while loop? Generally, when you know the number of iterations, you use a for loop. For indefinite looping, or looping until a condition changes, use a while or do..while loop. So, with the for loop, you typically will see loops that involve counting, whereas with while or do..while loops, often the evaluation uses boolean expressions. Regardless, you can use any looping structure to accomplish the desired task.

Putting Looping To Work

Let's create a project to experiment with these different kinds of loops.

Selecting File | New | Project. Change the project name to Looping and click OK.

Click the entry for Form1.cs and change it to Looping.cs. Change the form title bar's Text property in the Properties Window to Looping. Click to save your changes.

Modify the form to look like this:

Change each control's Name property to match the Name Property column below, and Text property to match the Text Property column. Arrange the controls similar to the image. Also, set the ReadOnly property of the reversedTextBox control to True. When you finish, click to save your changes.

ObjectName PropertyText Property
LabelsentenceLabelEnter sentence:
TextBoxsentenceTextBox
ButtoncountButtonCount
LabelletterCountLabelLetter count:
LabelreversedLabelReversed:
TextBoxreversedTextBox
CheckBoxanimateCheckBoxAnimate

Next, add event handlers for the countButton and animateCheckBox controls. You can either double-click on each control to automatically generate the default event handler code or, for each control, use the Properties Window, click the control, click the Events icon , and locate the event we need to handle for the control. For the countButton control, we need to handle the Click event, and for the animateCheckBox control, we need to handle the CheckedChanged event. Once you've located the correct event, you could type in the name of the handler, but in this case, it's much easier to just double-click each event. Studio generates an appropriate name for the event handler that consists of the name of the control, an underscore separator, and the event name.

Note In general, double-clicking a control will generate the typical event for this control, but you should still know how to find the other events for the control, and generate appropriate handlers for those events, as we'll have other non-default events we'll want to handle.

Modify the Looping.cs code as shown below. The event handler code was added previously.

Looping.cs
using ...

namespace Looping
{
    public partial class Looping : Form
    {
        public Looping()
        {
            InitializeComponent();
        }
        
        private void countButton_Click(object sender, EventArgs e)
        {
            int letterCount = 0;
            
            // Use for loop to find and count letters only.
            for (int i = 0; i < sentenceTextBox.Text.Length; i++)
            {
                // Determine if we have a character.
                if (char.IsLetter(sentenceTextBox.Text, i))
                    letterCount++;
            }
            
            letterCountLabel.Text = "Letter count: " + letterCount;
            
            // Use while loop to reverse. 
            StringBuilder reverseSB = new StringBuilder(sentenceTextBox.Text.Length);
            
            int letterPosition = sentenceTextBox.Text.Length;
            while (letterPosition > 0)
            {
                // Add character, working from end of string backwards.
                reverseSB.Append(sentenceTextBox.Text.Substring(--letterPosition, 1));
            }
        
            reversedTextBox.Text = reverseSB.ToString();
        }
        
        private void animateCheckBox_CheckedChanged(object sender, EventArgs e)
        {
        }
    }
}

and to run the program. Enter a short sentence in the text box that includes some numbers and a known number of letters, and click Count. The program should display the letter count and your sentence, backwards.

Let's discuss how this code works (we'll show it in two parts).

OBSERVE: Looping.cs, Part 1
.
.
.
        private void countButton_Click(object sender, EventArgs e)
        {
            int letterCount = 0;
            
            // Use for loop to find and count letters only.
            for (int i = 0; i < sentenceTextBox.Text.Length; i++ )
            {
                // Determine if we have a character.
                if (char.IsLetter(sentenceTextBox.Text, i))
                    letterCount++;
            }
            
            letterCountLabel.Text = "Letter count: " + letterCount;
.
.
.        

Our for loop declares and initializes a loop variable i (int i = 0), looping while the loop variable is less than the length of the string i < sentenceTextBox.Text.Length), and incrementing the loop variable for each iteration (i++). Notice that we use less than (<) rather than less than or equal to (<=). Why? Remember that for most objects, C# uses 0-based indexing, which means that the first element is at index, or position, 0. That also means that the final element in a 0-based object is going to be the length of the object minus 1. So, we loop while the loop counter is less than the length. So, this for loop counts the number of letters by incrementing letterCount, which we accomplish by calling the very suitable IsLetter method of char. This method has two parameters: the complete string to look at, and the position within that string to check.

What exactly is the flow of a for loop? It processes in the following order:

0. declaration and initialization 1. condition 2. code within the for loop block 3. iteration 4. goto Step 1

So, Step 0 only occurs once, and Step 2 is only reached if Step 1 is true. Of course, you can always exit the for loop using a break statement.

OBSERVE: Looping.cs, Part 2
.
.
.            
            // Use while loop to reverse. 
            StringBuilder reverseSB = new StringBuilder(sentenceTextBox.Text.Length);
            
            int letterPosition = sentenceTextBox.Text.Length;
            while (letterPosition > 0)
            {
                // Add character, working from end of string backwards.
                reverseSB.Append(sentenceTextBox.Text.Substring(--letterPosition, 1));
            }
            
            reversedTextBox.Text = reverseSB.ToString();
        }
.
.
.        

We next added a while loop to reverse the user-entered text. How this code works might not be obvious, but you might suspect something is strange when you see the --letterPosition code, which uses the pre-decrement operator. This while loop iterates as long as letterPosition > 0. We are effectively iterating backward through each element of the sentenceTextBox.Text, using the Substring method to extract that element. You should note that letterPosition is set to the length of sentenceTextBox.Text, and since this is an invalid position within the string, we use the pre-decrement operator to decrease the letterPosition variable by one before we attempt to extract the substring. We also are able to use letterPosition > 0 because of the pre-decrement. Work through this loop with a short sentence to make sure you understand how it works. How? When you run the program, you can set a break point and evaluate the value of letterPosition through each iteration, and see what first decrementing the position does for extracting the correct substring.

We also introduced an important class: StringBuilder. Whenever you're going to be creating a string result through concatenation (adding pieces of text to each other), consider using the StringBuilder class rather than a string data type. When you create a string, memory is allocated for the value of the string, and that memory is fixed, or what is often referred to as immutable. A simple string concatenation actually requires creating another temporary string in memory to hold the concatenated string result, reassigning the initial string to reference the new memory, and then deallocating the original memory. That's a lot of work, especially in a loop! Rather than concatenate with a string, you should use the StringBuilder class, which is optimized for such concatenation operations.

We've covered for and while loops; now let's add a do..while loop. For this loop, though, we'll have a bit more fun!

Add event handlers for the Looping Form Paint and FormClosing events; click on the title bar of the Looping Form in the Visual Designer, click the icon in the Properties Window, find the Paint event and double-click it. The Code Editor appears. Switch back to the Visual Designer, find the FormClosing event, and double-click it. Then, modify the Looping.cs code as shown below (again, our code is getting lengthy, so we'll just show the parts that we want to change).

Tip Simply adding the event handler code will NOT connect the event handler method to the control: you must either double-click the control to generate a handler for the default event for the control, or use the Events icon in the Properties Window.
Looping.cs
using ...

namespace Looping
{
    public partial class Looping : Form
    {
        bool doAnimation = false;
        .
        .
        .
        
        private void Looping_Paint(object sender, PaintEventArgs e)
        {
            string drawText = sentenceTextBox.Text.Length > 0 ? sentenceTextBox.Text : "Some text";
            // Determine our approximate stopping point.
            float maxWidth = e.Graphics.VisibleClipBounds.Width;
            // Set up starting x and y locations, noting that only the x is going to change.
            float x = animateCheckBox.Left;
            float y = animateCheckBox.Top + (animateCheckBox.Height * 2);
            // We'll need a previous x location so we can 'erase' the previous drawing.
            float previousX = x;
            
            // Loop until either we've reached our stopping point, or doAnimation is false.
            do
            {
                // Draw text at old location.
                e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(this.BackColor), previousX, y);
                // Make the system sleep for a short time so we can see the animation.
                System.Threading.Thread.Sleep(20);
                // Allow the program to process events so we can allow the user interface to be responsive after sleeping.
                Application.DoEvents();
                // Draw text at new location.
                e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(Color.Red), x, y);
                // Save the current location.
                previousX = x;
                // Advance to next location.
                x++;
            } while (x < maxWidth && doAnimation);
            
            // Do some cleanup.
            e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(this.BackColor), previousX, y);
            animateCheckBox.Checked = false;
            doAnimation = false;
        }
        
        private void animateCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            // Determine if we are to animate, then force paint event to occur using Refresh.
            doAnimation = animateCheckBox.Checked;
            this.Refresh();
        }
        
        private void Looping_FormClosing(object sender, FormClosingEventArgs e)
        {
            // We need to prevent, or cancel, closing, as code may still be in animation do loop.
            if (doAnimation)
            {
                MessageBox.Show("You must stop any animation before trying to close the program", this.Text, MessageBoxButtons.OK);
                e.Cancel = true;
            }
        }
    }
}
        

and to run the program. Enter a sentence and reverse it, and then check the Animate box and see what happens.

Let's discuss how this code works. First the Looping_Paint method:

OBSERVE: Looping.cs, part 1
        private void Looping_Paint(object sender, PaintEventArgs e)
        {
            string drawText = sentenceTextBox.Text.Length > 0 ? sentenceTextBox.Text : "Some text";
            // Determine our approximate stopping point.
            float maxWidth = e.Graphics.VisibleClipBounds.Width;
            // Set up starting x and y locations, noting that only the x is going to change.
            float x = animateCheckBox.Left;
            float y = animateCheckBox.Top + (animateCheckBox.Height * 2);
            // We'll need a previous x location so we can 'erase' the previous drawing.
            float previousX = x;
            
            // Loop until either we've reached our stopping point, or doAnimation is false.
            do
            {
                // Draw text at old location.
                e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(this.BackColor), previousX, y);
                // Make the system sleep for a short time so we can see the animation.
                System.Threading.Thread.Sleep(20);
                // Allow the program to process events so we can allow the user interface to be responsive after sleeping.
                Application.DoEvents();
                // Draw text at new location.
                e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(Color.Red), x, y);
                // Save the current location.
                previousX = x;
                // Advance to next location.
                x++;
            } while (x < maxWidth && doAnimation);
            
            // Do some cleanup.
            e.Graphics.DrawString(drawText, new Font("Arial", 8), new SolidBrush(this.BackColor), previousX, y);
            animateCheckBox.Checked = false;
            doAnimation = false;
        }
 
        private void animateCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            // Determine if we are to animate, then force paint event to occur using Refresh.
            doAnimation = animateCheckBox.Checked;
            this.Refresh();
        }
        

As you can see, we've added code that uses the DrawString method to effectively make whatever text the user types in to appear to move, or animate, across the screen, by selecting the animateCheckBox control. If no text is entered, we use the conditional/ternary operator we've learned (? :) to use some default text. We use the do..while loop to iterate through all possible x positions across the screen, after setting a starting point below the animateCheckBox. We use a compound conditional statement, x < maxWidth && doAnimation, to make sure we stop trying to animate once we've reached the maximum x position, or if doAnimation becomes false.

What is the purpose of the doAnimation class variable? The method we've used to animate the text is not the best solution for this type of action, but we wanted to illustrate the do..while loop. A better solution would be a timer event, but that wouldn't require a loop. We had to use the Sleep method to slow down the drawing of our text; otherwise, the text would draw so quickly you wouldn't see the animation. Also, we had to use a DoEvents method to allow our code to process any events that might have been queued while the Sleep method was called. Within our do..while loop, we want to be able to uncheck the animateCheckBox to effectively stop the animation, which is accomplished by changing the doAnimate variable to false. We also added a call to the Looping Form Refesh method, which triggers the Paint event, thus calling the Looping_Paint method.

Now let's look at the Looping_FormClosing method:

OBSERVE: Looping.cs, part 3
        private void Looping_FormClosing(object sender, FormClosingEventArgs e)
        {
            // We need to prevent, or cancel, closing, as code may still be in animation do loop.
            if (doAnimation)
            {
                MessageBox.Show("You must stop any animation before trying to close the program", this.Text, MessageBoxButtons.OK);
                e.Cancel = true;
            }
        }

The Looping_FormClosing method handles any attempt to close the Looping form. We didn't add a button to allow the user to close the form, so if they want to close it, they must click the , which triggers the FormClosing event, thus calling this method, which is linked to handle this event. If they try to close the form while the text is animating, when the do..while code executes the DoEvents line, our code will suspend while the method handles the FormClosing event. Trying to exit while the do..while code is exiting could lead to the Looping form appearing to close, but actually just disappearing—and then the program returning to finish the do..while loop, then finally closing. For our code, this scenario isn't a big deal, but we'd rather introduce this concept of event-driven coding now, as we'll see more such scenarios in the future, and will need to learn how to properly handle asynchronous events (events received in an unspecified order). For now, we display a MessageBox, and cancel the closing of the form by setting the Cancel property to true.

So how exactly are we making the text appear to animate? Each iteration through the do..while loop, we first "erase" the existing text by drawing it in the same color as the background at its previous position (previousX), then we increment the x value and draw the text in red at the new position. When the loop is concluded, we again draw the text at the previousX position to erase it one last time. That's it!

Before you move on to the next lesson, do your homework! Right-click in the window where this lesson text appears and select Back. Then select Quiz for this lesson in the syllabus and answer the quiz questions. When you finish the quiz questions, click Hand it in at the bottom of that window. Then do the same with the Project(s) for the lesson. Your instructor will grade your quiz(zes) and project(s) and provide guidance if needed.