Round And Around
Last time, I introduced you to C#’s “if-else” family of conditional statements, and explained how they could be used in combination with comparison and logical operators to control program flow and execution. I also explained how conditional statements could be nested within one another, and wrapped things up with a discussion of the “switch” conditional statement.
This week, I’m going to proceed a little further down the road, with a look at the different types of loops supported by C# (and, by extension, ASP.NET). As always, I’ll begin with a definition for those of you coming at this series from a non-programming background. In geek-talk, a “loop” is precisely what you would think - a programming construct that allows you to execute a set of statements over and over again, until a pre-defined condition is met.
C# offer a wide range of loops, in keeping with its profile as a next-generation programming language. It has the “while” and “do-while” loops, for situations involving a variable number of loop iterations, as well as the traditional “for” loop for loops involving a pre-defined number of iterations. Over the next few pages, I’ll explain these loops in greater detail, together with examples and illustrations of how they can be used.
Every programming language worth its salt uses loops - and, incidentally, so do many shampoo manufacturers. Think lather-rinse-repeat, and you’ll see what I mean…
Counting Down
The most basic loop available in C# is the “while” loop, and it looks like this:
while (condition)
{
do this!
}
Or, to make the concept clearer,
while (rich Uncle Ed's still breathing)
{
be nice to him
}
The “condition” here is a standard C# conditional expression, which evaluates to either true or false. So, were you told to write the above example in C#, it would look like this:
while (rich_old_guy_lives == 1)
{
be_nice();
}
The “while” control structure tests the conditional expression first, and only proceeds to execute the statements within the loop if the expression evaluates to true.
How about an example to demonstrate the “while” loop?
<script language="C#" runat="server">
void Page_Load()
{
// define a variable for the countdown
int countdown = 10;
output.Text = "Beginning countdown...";
// repeat the statement so long as the
// variable is greater than or equal
// to zero
while(countdown >= 0)
{
output.Text += "<br>" + countdown;
countdown--;
}
output.Text += "<h1>Houston, we have lift-off!</h1>";
}
</script>
<html>
<head><title>Countdown To Launch</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>
Here is the output.
Each loop requires a variable, or “loop counter”, to track the number of iterations. In the example above, this variable is called “countdown”. I have initialized it to 10, since the loop will start counting down from that value.
Next, we have the “while” loop proper:
<%
while(countdown >= 0)
{
output.Text += "<br>" + countdown;
countdown--;
}
%>
This is pretty straightforward stuff. The “while” statement will check if the value of the “countdown” variable is greater than or equal to zero. If it is, it will enter the loop and execute the enclosed statements (in this case, print the value of the variable followed by a line break). It then decrements the value of the “countdown” variable by one (using the – operator discussed previously), and repeats the procedure.
On the eleventh iteration, the value of the countdown variable will be -1. Therefore, the result of the conditional statement will be false, the loop will be exited and the statements following the loop will be processed.
What if you forget to decrement the value of the loop counter (a common newbie mistake)? Start praying, and flip the page.
The Infinite Loop and the Careless Coder
A word of caution to novice programmers (and careless experienced ones also): if you fail to provide a valid condition to exit your loop, you will get stuck in an infinite loop, one of the worst nightmares for a developer.
The likely symptom of this condition in the ASP.NET context is a server that fails to respond for an extended period of time while executing the script. In such a situation, you can rest assured that an infinite loop is the most likely culprit. Don’t take my word for it, try it for yourself (note that the following code deliberately introduces an infinite loop for illustrative purposes, so use it at your own risk):
<script language="C#" runat="server">
void Page_Load()
{
// define a loop counter
int countdown= 10;
output.Text = "Beginning countdown...";
// repeat
while(countdown >= 0)
{
output.Text += "<br>" + countdown;
// don't change the loop counter, thereby introducing
// an infinite loop
// countdown--;
}
output.Text += "<h1>Houston, we have lift-off!</h1>";
}
</script>
<html>
<head><title>Countdown To Launch</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>
This example deliberately “forgets” to alter the value of the loop counter every time the loop runs. As a result, the conditional test always ends up true and the script never exits the “while” loop. Hence, the Web server continues to execute the script (and eat memory) till such time as you forcibly terminate the script by shutting down the server, or the server times out.
Since Web servers can’t rely on a human being around 24/7 to monitor the server and kill rogue scripts, most of them include built-in safeguards to ensure that such rogue scripts do not completely take over system resources. They do this by including a timeout period, which specifies the maximum amount of time given to a particular script to complete execution. If the script exceeds this time limit, the Web server will automatically halt further execution of the script and return an error. For the IIS server, you can modify this value using the Internet Service Manager; read more about this at http://www.microsoft.com/windows2000/en/server/iis/htm/core/iipy_32.htm.
Note, however, that just because the Web server has this built-in timeout capability, it is not an excuse for you, the developer, to write sloppy code; until the server timeout is activated, other requests will be queued unnecessarily, affecting the performance of the server and annoying your users. Therefore, it is important to always ensure that your loop has a valid exit condition…because prevention is better than cure!
Dos and Don’ts
A close cousin of the “while” loop is the “do-while” loop, which generally looks like this:
do
{
do this!
} while (condition)
Wondering what the difference is between this one and the previous one? Try this next example in your browser:
<script language="C#" runat="server">
void Page_Load()
{
int bingo = 366;
// script will never enter the loop
// since the condition is false
while (bingo == 699)
{
output.Text = "Bingo!";
}
}
</script>
<html>
<head><title>Dos and Don'ts</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>
And here is the output:
What output?
The reason for the blank page is simple. If you take a closer look at the code listing above, you will notice that the conditional statement evaluates to false at the first iteration itself. As a result, the script never enters the “while” loop.
Now, there may be occasions when you need to execute a particular set of statements at least once before you check for a valid conditional expression. Consider the example of an interactive session with a store manager adding items to the store inventory. You might want to force him to add at least one item. Once he has added a single item, you can ask if he wishes to add more; if yes, allow him to continue, otherwise terminate the session. A “do-while” loop fits this situation well: the construction of the “do-while” loop is such that the statements within the loop are executed first, and the condition to be tested is checked after.
The next example will demonstrate this:
<script language="C#" runat="server">
void Page_Load()
{
int bingo = 366;
do
{
output.Text = "Bingo!";
} while (bingo == 699);
}
</script>
<html>
<head><title>Dos and Don'ts</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>
And here is the output:
In this case, the script will always execute the statements within the loop at least once. Subsequent iterations are subject to the evaluation of the conditional expression of the “do-while” loop. In the example above, the expression evaluates to false, resulting in immediate exit from the loop after the first iteration. This is clearly seen in the output above.
How about another example to make things clearer? This next one rewrites the countdown example using the “do-while” loop below:
<script language="C#" runat="server">
void Page_Load()
{
// define a loop counter
int countdown= 10;
output.Text = "Beginning countdown...";
// repeat so long as the variable
// is greater than or equal to zero
do {
output.Text += "<br>" + countdown;
countdown--;
} while (countdown >= 0);
output.Text += "<h1>Houston, we have lift-off!</h1>";
}
</script>
<html>
<head><title>Countdown To Launch</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>
And here’s the output:
The bottom line: using a “do-while” loop ensures that the code within the loop will be executed at least once, regardless of whether or not the conditional expression evaluates as true.
For-gone Conclusion
Both the “while” loop and its close cousin, the “do-while” loop, are used when you don’t know for certain how many times the program should loop. But C# also comes with a mechanism for executing a set of statements a specific number of times - and it’s called the “for” loop:
for (initial value of counter; condition; update counter)
{
do this!
}
Looks like gibberish? Well, hang in there a minute…the “counter” here is a C# variable that is initialized to a numeric value, and keeps track of the number of times the loop is executed. Before each execution of the loop, the “condition” is tested - if it evaluates to true, the loop will execute once more and the counter will be appropriately incremented; if it evaluates to false, the loop will be broken and the lines following it will be executed instead.
Let’s look at an example:
<script language="C#" runat="server">
void Page_Load()
{
int number = 7;
// use a for loop to calculate tables for that number
for (int x=1; x<=15; x++)
{
output.Text += number + " X " + x + " = " + (number*x) + "<br>";
}
}
</script>
<html>
<head><title>Turning The Tables, ASP.NET-Style!</title></head>
<body>
<h3>Turning The Tables, ASP.NET-Style!</h3>
<asp:label id="output" runat="server" />
</body>
</html>
And here’s the output:
Let’s dissect this a little bit.
<%
int number = 7;
%>
Right up front, a variable is defined, containing the number to be used for the multiplication table. I’ve used 7 here - you might prefer to use another number.
<%
// use a for loop to calculate tables for that number
for (int x=1; x<=15; x++)
{
output.Text += number + " X " + x + " = " + (number*x) + "<br>";
}
%>
Next, a “for” loop has been constructed, with “x” as the counter variable. If you take a look at the first line of the loop, you’ll see that “x” has been initialized to 1, and is set to run no more than 15 times.
Finally, the script takes the specified number, multiplies it by the current value of the counter, and displays the result on the page by virtue of the “Text” attribute of the “output” label server control.
The Sound Of Breaking Loops
When dealing with loops, there are two important keywords you should be aware of: “break” and “continue”. You might remember that I dealt with these briefly in the previous section of this tutorial; let’s now take a closer look, since these keywords come in handy when dealing with loops as well.
First, the “break” keyword. This is usually used to exit a loop when it encounters an unexpected situation. A good example of such a situation is the dreaded “division by zero” error: when dividing one number by another one (which keeps decreasing), it is always advisable to check the divisor on every iteration and take action (either exit the loop or skip to the next iteration) once it becomes equal to zero.
Take a look:
<script language="C#" runat="server">
void Page_Load()
{
// some variables to play with
int dividend = 7;
int divisor = 10;
// a for loop to perform division
for(int count = 1; count <= 15; count++)
{
// if divisor is zero
// get out now
if(divisor == 0)
{
break;
}
// print loop counter and perform division
output.Text += "Loop counter is " + count + "." + " ";
output.Text += dividend + " / " + divisor + " = " +
((double)dividend/divisor) + "<br>";
// decrement divisor
divisor--;
}
output.Text += "<h3>Divisor is zero, time to stop!</h3>";
}
</script>
<html>
<head></head>
<body>
<h3>Divide And Conquer</h3>
<asp:label id="output" runat="server" />
</body>
</html>
Here’s the output:
In this example, I have defined two variables, a dividend and a divisor. Next, I’ve used a “for” loop to divide the two values by each other a fixed number of times (15). Note that I have also decremented the value of the “divisor” variable by one for every iteration of the loop.
Obviously, at some point of time, “divisor” will become zero. Any attempt to continue division after this point will result in ugly C# error messages about illegal operations. This is where the “break” statement comes in - it can be used to exit the “for” loop as soon as the value of the variable “divisor” becomes zero.
Should I pat myself on my back? Not really.
Take another look at the output and compare it against the code listing. You will see that the code exited the “for” loop before the condition for the loop became false.
Ideally, the script should exit the “for” loop when the value of the “count” variable becomes greater than 15, and, until then, should perform division for all values of the divisor other than 0 (including negative values).
In the example above, the “break” statement caused it to exit once the divisor becomes 0 (on the tenth iteration of the loop). Therefore, only positive divisor values are taken care of by the code above; division operations involving negative values of the divisor never even see the light of day.
Is there a way to fix this? Sure, with the “continue” keyword. Take a look:
<script language="C#" runat="server">
void Page_Load()
{
// some variables to play with
int dividend = 7;
int divisor = 10;
// a for loop to perform division
for(int count = 1; count <= 15; count++)
{
// if divisor is zero
// decrement divisor and continue
if(divisor == 0)
{
divisor--;
continue;
}
// print loop counter and perform division
output.Text += "Loop counter is " + count + "." + " ";
output.Text += dividend + " / " + divisor + " = " +
((double)dividend/divisor) + "<br>";
divisor--;
}
output.Text += "<h3>All done, time to stop!</h3>";
}
</script>
<html>
<head></head>
<body>
<h3>Divide And Conquer</h3>
<asp:label id="output" runat="server" />
</body>
</html>
Here’s the output:
In this revised example, when the value of the “divisor” variable becomes zero, I decrement its value and call the “continue” keyword. This “continue” keyword skips over the current iteration of the loop and send control of the program back to the start of the “for” loop for the next iteration (unlike the “break” statement, which simply exits the loop immediately). As a result, the script continues to iterate through the “for” loop until the conditional statement is no longer true, and the value of the “count” variable becomes greater than 15.
For obvious reasons, there is no output for that particular iteration of the loop when the value of “divisor” variable is zero.
End Of Play
And that’s about it for this article. Over the last few pages, I listed the different types of loops available to C# programmers, and showed you how they can be used. I started with the “while” loop, used to repeat a set of statements until a given condition becomes false. Its close cousin, the “do-while” loop, is used to ensure that a “while” loop executes at least once, regardless of the state of the conditional expression.
For situations which don’t involve as much uncertainly about the total number of loop iterations, there’s the “for” loop, useful when you know the exact number of iterations the loop should run for. Finally, I demonstrated the “break” and “continue” keywords, which come in handy to exit a loop and skip over particular iterations of the loop, respectively.
That’s about all we have time for this week. Next week, I shall introduce you the wonderful world of complex variables - arrays, enumerations and structures - that build on the simple variables you’ve encountered thus far to allow more complex storage and manipulation of data. Until then, practice, practice, practice - because only practice makes perfect!
Note: Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
This article was first published on 29 Aug 2003.