|
|
|
During the course of writing a program, you'll find many cases where you want to repeat the same basic logic many times in a row. One obvious way to do that would be using "copy and paste" to duplicate the same block of code as many times as we need it to run. But what if that code block is 300 lines long, and we want it repeated 5000 times? Worse still, what if you need the same basic logic to run 5000 times, except that each time, there's a tiny change? For example, if you want to print the numbers 1 to 5000 on the console, you don't want to copy and paste 4999 WriteLine() statements, and then go back and change the number on each line! And fortunately, you don't have to. Here's a block of code that does this very thing, in just a few lines... int num = 0; while( num < 5000 ) { num = num + 1; Console.WriteLine( num ); } Yes, in addition to the "if" statement we learned last time, we now have the "while" loop. The syntax of this expression follows the same pattern set out by the "if" statement: you have a keyword, followed by a pair of ( ) with a Boolean expression in them, followed by a pair of { } with lines of code in them. The "if" statement, however, makes a one-time decision based on a logical expression, whereas "while" loop is designed to endlessly repeat the code within its { } pair, until the logical expression is false. In this case, that means that the while loop will continuously increase num by 1, and print its current value to the screen, until num is no longer less than 5000. If we wanted the code to loop one million times, we'd simply change the "5000" to a "1000000". An important thing to note here is that there's no guarantee that the code in the while loop will ever run. If num is already greater than or equal to 5000 when it hits the while statement, then the statement will already be false, and the code won't run even once. And speaking of Boolean expressions, what do you think would happen if we were to do this? while( true ) { Console.WriteLine( "No end in sight..." ); } If the Boolean expression in the ( ) never evaluates to false, then your program will never leave the while statement. In other words, the above code will cause your program to become trapped in an "infinite loop", doomed to repeat the same lines of code over and over and over until someone graciously intervenes and kills the program manually (by closing the window or hitting CTRL + ALT + DEL). Nor do we need a Boolean constant of "true" to trap our program. It's very easy to create an infinite loop by accident... int num = 0; while( num < 5000 ) { num = num - 1; Console.WriteLine( num ); } The above code snippet looks almost identical to the original one, with one fatal difference... the programmer foolishly used a "-" sign, instead of a "+" sign. So "num" is never going to become greater or less than 5000, because it started at zero and goes further into the negative with each pass through the loop. As a result, the program will become trapped in the loop. There are two other keywords associated with loops, and they are "continue" and "break". Here's an example: int num = 0; while( num < 5000 ) { num = num + 1; if( num == 5 ) continue; if( num == 1000 ) break; Console.WriteLine( num ); } The "continue" keyword tells the loop to stop executing the loop it's currently on, and start it's next trip through the loop right away. So in the above code snippet, the number "5" will never print to the screen, because the program will encounter a "continue" keyword before the WriteLine() when num is equal to 5. The "break" keyword is even more severe; it tells the program to break out of the loop entirely. So in the above code snippet, the last number to print to the screen will be 999, because when num is equal to 1000, the program encounters the "break" keyword and exits the loop. Of course, in the above example, it would make far more sense just to change the "while loop" condition to "num < 999", and then we wouldn't need the break statement at all, because the loop would terminate naturally. "break" becomes more useful when you want to check a large number of values, but stop checking as soon as you've found the one you're looking for. A note about "continue" and "break"... some programmers don't like using them, citing that they can make code difficult to read and encourage sloppy coding habits. This is certainly a fair argument. Personally, I don't avoid using them... but if you decide to make use of them, make sure that isn't because you want a "quick and dirty" solution. Logic that, at first, might seem to require a "continue" or "break" can often be solved by adding a little extra logic to the loop itself (as mentioned in the previous paragraph). Okay, two more things, and then we'll move on to the next lesson. Did you see how we were increasing the value of num by adding one to itself? Programmers have to perform this kind of operation all the time, and there's a handy shortcut you can use when you want to do it: num += 1; This means exactly the same thing as "num = num + 1", but in fewer "words". And, as you might expect, there are equivalent shortcuts for the other primary math operators: num -= 5; // num = num - 5; num *= 2; // num = num * 2; num /= 9; // num = num / 9; num %= 3; // num = num % 3; By far, the most common way to increment a number is to increase/decrease it by 1. So, there's even a special shortcut for that: ++num; --num; These two expressions change the value of num by +1 and -1, respectively. For the record, you can put the double operator after the variable, as in "num++" and "num--", but don't bother, because that's actually less efficient. Why? Okay, just this once, I'll humor your insatiable curiosity. When C# reads "++num" ("pre-increment"), all it does is add one to the value. Easy as pie. But when it reads "num++" ("post-increment"), it creates a temporary copy of "num" in memory, increases the copy's value by one, and then assigns the value of the copy back to the original variable. Now, I'll grant that with today's processor speeds, you're not going to notice the difference in execution time, unless you're doing thousands upon thousands of increment operations. But even so, if they both do the same thing, but post-increment is less efficient, then why use it? Stick with pre-increment, unless there's a really good mathematical reason to use post-increment. Lastly, I'd just like to point out that one of the most common and best uses of the "while" loop revolves around user input. If your program needs a specific kind of value, you can use a while loop to keep prompting the user for input until they finally get it right. For example, say that you needed the user to input a name that was exactly five characters long... string name = ""; while( name.Length != 5 ) { Console.Write("Enter a five letter name: "); name = Console.ReadLine(); if( name.Length != 5 ) Console.WriteLine("No, no, no! Pay attention to what I'm asking!" + Environment.NewLine); } Console.WriteLine("Good. That name's the correct length."); See? And of course, that basic idea can be adapted to cover pretty much any restriction on user input that you want. Our next topic is a specialized cousin of the "while" loop, the "for" loop. But first, let's pause for our usual mandatory code sample... using System; namespace B_While { class Class1 { [STAThread] static void Main(string[] args) { // Continually run this code until the expression becomes false // Loop until total is greater than or equal to 100 int total = 0; while( total < 100 ) { Console.WriteLine("Current Sum: " + total); Console.Write("Add how much to sum? "); int addAmount = Convert.ToInt32( Console.ReadLine() ); total += addAmount; Console.WriteLine(""); } Console.WriteLine("Limit exceeded! Current Sum: " + total + Environment.NewLine); // Count upward int count = 0; while( count < 5 ) { ++count; Console.WriteLine( count ); } Console.WriteLine("Finished counting." + Environment.NewLine); // Continually run this code until the expression becomes false // Loop until name length is five string name = ""; while( name.Length != 5 ) { Console.Write("Enter a five letter name: "); name = Console.ReadLine(); if( name.Length != 5 ) Console.WriteLine("No, no, no! Pay attention to what I'm asking!" + Environment.NewLine); } Console.WriteLine("Good. That name's the correct length."); // Prompt for exit Console.Write(Environment.NewLine + "Program complete! Hit enter to exit..."); Console.ReadLine(); } } } |
|