User:Foxall/15

Ka Wiktionary

Hour 15. Looping for Efficiency[wax ka badal]

graphics/newterm.gif As you develop your C# programs, you'll encounter situations in which you'll need to execute the same code statement or statements repeatedly. Often, you'll need to execute these statements a specific number of times, but you may need to execute them as long as a certain condition persists (an expression is true) or until a condition occurs (an expression becomes true). C# includes constructs that enable you to easily define and execute these repetitive code routines: loops. This hour shows you how to use the two major looping constructs to make your code smaller, faster, and more efficient.

The highlights of this hour include the following:

  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch15lev1sec1.htm#ch15lev1sec1 Looping a specific number of times using for statements]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch15lev1sec2.htm#ch15lev1sec2 Looping an indeterminate number of times using do…while and while statements]

Looping a Specific Number of Times Using for Statements[wax ka badal]

The simplest type of loop to create is the for loop, which has been around since the earliest forms of the BASIC language. With a for loop, you instruct C# to begin a loop by starting a counter at a specific value. C# then executes the code within the loop, increments the counter by a defined incremental value, and repeats the loop until the counter reaches an upper limit you've set. The following is the syntax for the basic for loop:

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

Initiating the Loop Using For

The for statement both sets up and starts the loop. The for statement has the components shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/15.htm#ch15table01 Table 15.1].

Part Description
initializers A comma-separated list of expressions or assignment statements to initialize the loop counters.
expression An expression that can be implicitly converted to boolean. The expression is used to test the loop-termination criteria.
iterators Expression statement(s) to increment or decrement the loop counters.
statement The embedded statement(s) to execute.

The following is a simple example of a for loop, followed by an explanation of what it's doing:

for (int intCounter = 1; intCounter <= 100; intCounter++)
 Debug.WriteLine(intCounter);

This for statement initializes an Integer named intCounter at 1; the condition intCounter <= 100 is tested and returns true; therefore, the statement debug.WriteLine(lngCounter) is executed. After the statement(s) are executed, the variable intCounter is incremented (intCounter++). This loop would execute 100 times, printing the numbers 1 through 100 to the Output debug window.

graphics/bookpencil.gif To use the Debug object, you need to use the System.Diagnostics namespace.

To execute multiple statements within a for loop, braces { } are used; a single line for statements does not require braces. Here is the previous for loop written to execute multiple statements:

for (int intCounter = 1; intCounter <= 100; intCounter++)
{
 Debug.WriteLine(intCounter);
 Debug.WriteLine(intCounter-1);
}

Exiting a for Loop Early

There may be times when you'll want to terminate a for loop before the expression evaluates to true. To exit a for loop at any time, use the break statement.

 Building a for Loop Example 

You're now going to create a method containing two for loops�one nested within the other. The first loop is going to count from 1 to 100 and set the Width property of a Label control to the current counter value; this will emulate a Windows progress meter. The second loop will be used to slow the execution of the first loop�an old programmer's trick using a for loop.

Create a new Windows Application named ForExample. Set the form's Text to For Statement Example. Add a Label control to the form by double-clicking the Label tool in the toolbox. Set the label's properties as follows:

Property Value
Name lblMeter
BackColor (Set to a light blue or any color you like.)
Location 100,100
Text (make blank)
Size 100,17

Next, add a button to the form by double-clicking the Button item in the toolbox. Set the button's properties as follows:

Property Value
Name btnForLoop
Location 88,125
Size 125,23
Text Run a For Loop

Your form should look like the one shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/15.htm#ch15fig01 Figure 15.1].

Figure 15.1. This simple project will emulate a progress meter.

graphics/15fig01.jpg

All that's left to do is to write the code. Double-click the button to access its Click event and enter the following:

for (int intLabelWidth=1; intLabelWidth<=100; intLabelWidth++)
{
 lblMeter.Width = intLabelWidth;
 lblMeter.Refresh();
 for (int intPauseCounter=1; intPauseCounter<=600000; intPauseCounter++);
}
graphics/bookpencil.gif Using a loop to create a delay is actually a very poor and outdated coding technique. Other options can be used for creating a delay, such as calling System.Threading.Thread.Sleep(). This example is designed to illustrate nested loops�which it does, not to show the best way to create a delay.
graphics/bookpencil.gif Remember that C# is case sensitive. (Hint: for, int, and long are all lowercase).

The first line starts the first for loop. It starts by creating and initializing the variable intLabelWidth; next comes an expression used to evaluate the variable, and the third part is the iterator, which increments intLabelWidth by one each time the loop completes.

The first statement within this for loop sets the width of the Label control to the value of intLabelWidth. The next statement calls the Refresh method of the Label control to ensure that it paints itself. Often, painting catches up when the CPU has idle time. Because you want the transition from a small label to a large one to be smooth, you need to make sure the label paints itself after each update to its Width property. After all the statements within the braces execute, intLabelWidth is incremented by one (intLabelWidth++) and the expression is evaluated once more. This means that the code within the loop will execute 100 times.

The next statement starts a second for loop using the intPauseCounter variable, creating and initializing intPauseCounter to 1 and setting the upper limit of the loop to 600,000. Following this for statement is a semicolon(;) with no statement before it. This creates an empty statement. Why is there no code for this for statement of the lngPauseCounter loop? This loop is used simply to create a delay within the processor. Most computers are so fast that if you didn't add a delay here, the first for loop would update the label's width from 1 to 100 so fast that you might not even see it update!

graphics/bookpencil.gif I wrote this code on a 1.33GHz (1,333MHz) machine; you may have to alter this value if your processor speed is much different. If you have a slower CPU, reduce this value. If you have a much faster processor, increase this value. Wait until you test this code before making changes to the upper limit, however. Again, using another method, such as calling System.Threading.Thread.Sleep(), would allow precise control over the delay, regardless of the speed of the machine.

Click Save All on the toolbar and press F5 to run the project. The label starts with a width of 100. Click the button, and you'll see the label's width change to 1 and then increment to 100. If the speed is too slow or too fast, stop the project and adjust the upper limit of the inner for loop.

If you were to forgo a loop and write each and every line of code necessary to draw the label with a width from 1 to 100, it would take 100 lines of code. Using a simple for loop, you performed the same task in just a few lines. In addition, a for loop allowed you to create a pause during the update.

A for loop is best when you know the number of times you want the loop to execute. This doesn't mean that you have to actually know the number of times you want the loop to execute at design time; it simply means that you must know the number of times you want the loop to execute when you first start the loop. You can use a variable to define any of the arguments of the for loop, as illustrated in the following code:

int intUpperLimit=100;
for (int intCounter=1; intCounter<=intUpperLimit;intCounter++)
 Debug.WriteLine(intCounter);
graphics/bulb.gif One of the keys to writing efficient code is to eliminate redundancy. If you find yourself typing the same (or a similar) line of code repeatedly in the same procedure, chances are it's a good candidate for a loop (and you may even want to place the duplicate code in its own method).

Using do…while to Loop an Indeterminate Number of Times

In some situations, you won't know the exact number of times a loop needs to be performed�not even when the loop begins. When you need to create such a loop, using the do…while loop is the best solution.

The do…while comes in a number of flavors. Its most basic form has the following syntax:

do statement while (expression); 
graphics/bookpencil.gif The following is used to execute multiple statements:
do<br />{<br />[Statements]<br />} while (expression); 
Ending a do…while 

A do…while without some sort of exit mechanism or defined condition is an endless loop. In its most basic form, nothing is present to tell the loop when to stop looping. At times you may need an endless loop (game programming is an example), but more often, you'll need to exit the loop when a certain condition is met. Like the for loop, you can use the break statement to exit a do…while loop at any time. For example, you could expand the do…while we're discussing to include a break statement like the following:

do
{
 [Statements]
 if (expression)
 break;
} while (x==x); 

In this code, the loop would execute until expression evaluates to true. Generally, the expression is based on a variable that's modified somewhere within the loop. Obviously, if the expression never changes, the loop never ends.

The second flavor of the while loop is the while…do loop. The following is a simple while…do loop:

while (expression) statement 

As long as expression evaluates to true, the loop continues to occur. If expression evaluates to false when the loop first starts, the code between the statement(s) doesn't execute�not even once.

The difference between the do…while and the while…do loops is that the code statements within the do…while loop always execute at least once; expression isn't evaluated until the loop has completed its first cycle. Therefore, such a loop executes at least once, regardless of the value of expression. The while loop evaluates the expression first; therefore, the statements associated with it may not execute at all.

 Creating a do…while Example 

You're now going to create an example using a do…while loop that updates a label to once again simulate a progress meter. This loop performs the same purpose as the for loop you created in the previous example, but its structure is quite different.

If your for example is currently running, choose Stop Debugging from the Debug menu. Add another button to the formand set the new button's properties as follows:

Property Value
Name btnDoLoop
Location 88,160
Size 125,23
Text Run a Do Loop

Your form should now look like the one shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/15.htm#ch15fig02 Figure 15.2].

Figure 15.2. You'll use the same form for both loop examples.

graphics/15fig02.jpg

Double-click the new button to access its Click event and then enter the following code:

int intLabelWidth=1;

while (intLabelWidth != 100)
{
 lblMeter.Width = intLabelWidth;
 lblMeter.Refresh();
 intLabelWidth++; // Increment by one.
 for (int intPauseCounter=1; intPauseCounter<=600000; intPauseCounter++);
}

Again, this code is more easily understood when broken down, as shown in the following list:

  • The first line creates the intLabelWidth variables and sets it to 1.
  • A while statement is used to start a loop. This loop will execute until intLabelWidth has the value 100. It can also be read as "the statements will execute while intLabelWidth does not equal 100."
  • The Label's Width property is set to the value of intLabelWidth.
  • The Label is forced to refresh its appearance.
  • The intLabelWidth variable is incremented by 1.
  • A for loop is used to slow down the procedure, just as it was in the previous example. Again, this is just to illustrate nested loops. Calling System.Threading.Thread.Sleep() would be a better way to create a delay.
  • Click Save All on the toolbar to save the project, and then press F5 to run it. Click the Run a Do Loop button to see the progress meter set itself to 1 pixel and then update itself by 1 until it reaches 100 pixels.
graphics/bookpencil.gif I wanted to show you how both types of loops could be used to accomplish the same task. In this example, however, the for loop is clearly the best approach because you know the starting values and the number of times to loop when the loop starts.

You've now seen how to perform the same function with two entirely different coding techniques. This is fairly common when creating programs; usually, multiple ways exist to approach a solution to a given problem. Simply being aware of your options makes writing code that much easier. When you hear of people optimizing their code, they're usually looking for a different, faster approach to a problem they've already solved.

>

Summary

Looping is a powerful technique that allows you to write tighter code. Tighter code is code consisting of fewer lines, is more efficient, and is usually�but not always�more readable. In this hour, you learned to write for loops for situations in which you know the precise number of times you want a loop executed. Remember, it's not necessary to know the number of iterations at design time, but you must know the number at runtime to use a for loop. You learned how to use iterators to increment the counter of a for loop, and even how to exit a loop prematurely using break.

In this hour, you also learned how to use the very powerful do…while loop. The do…while loop enables you to create very flexible loops that can handle almost any looping scenario. You learned how evaluating expression in a do…while loop makes the loop behave differently than when evaluating the expression in a while…do loop. If a for loop can't do the job, some form of the do…while or while…do loop will.

In addition to learning the specifics about loops, you've seen firsthand how multiple solutions to a problem can exist. Often, one approach is clearly superior to all other approaches, although you may not always find it. Other times, one approach may be only marginally superior, or multiple approaches may all be equally applicable. Expert programmers are able to consistently find the best approaches to any given problem. With time, you'll be able to do the same.

Q&A
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/15.htm#qad1e47323 Q1:] Are there any specific cases in which one loop is appropriate over another?
A1: Usually, when you have to walk an index or sequential set of elements (such as referencing all elements in an array), the for loop is the best choice.
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/15.htm#qad1e47333 Q2:] Should I be concerned about the performance differences between the two types of loops?
A2: With today's fast processors, chances are good that the performance difference between the two loop types in any given situation will be overshadowed by the readability and functionality of the best choice of loop. If you have a situation in which performance is critical, write the loop using all the ways you can think of, benchmark the results, and choose the fastest loop.

Workshop

The Workshop is designed to help you anticipate possible questions, review what you've learned, and get you thinking about how to put your knowledge into practice. The answers to the quiz are in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01.htm#app01 Appendix A], "Answers to Quizzes/Exercises."

 Quiz
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec15.htm#ch15ans01 1:] True or False: You have to know the start and end values of a for loop at design time to use this type of loop.
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec15.htm#ch15ans02 2:] Is it possible to nest loops?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec15.htm#ch15ans03 3:] What type of loop would you most likely need to create if you didn't have any idea how many times the loop would need to occur?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec15.htm#ch15ans04 4:] If you evaluate the expression in a do…while on the while statement, is it possible that the code within the loop may never execute?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec15.htm#ch15ans05 5:] What statement do you use to terminate a do…while without evaluating the expression on the do or while statements?
Exercises
  1. The status meter example using do…while has a deliberate "bug." The meter will display only to 99 (the label's width will adjust only to 99 pixels, not 100). The problem has to do with how the expression is evaluated. Find and correct this problem.
  2. Use two for loops nested within each other to size a label in two dimensions. Have the outer loop change the Width of the label from 1 to 100 and have the inner loop change the Height from 1 to 100. Don't be surprised by the result�the end result is rather odd.