Common Concepts of Programming Part 5 – Loops and Repetition

Introduction

During the prior article, we looked at the basics of using logic to control the flow of our program. The logic involved testing for certain values in variables, and executing different blocks of code based on the outcome of those tests.

This is valuable, to be sure; but what are we to do if we need to repeat a particular segment of code multiple times? Do we want to set the same code into our application over and over? Unless we have a fixed number of repetitions that is very small, this is anything but efficient.

For example, what if we wanted to execute our HelloAdvancedWorld project multiple times without needing to restart it each time? What if we wanted to say hello to multiple people at once? What if we want to force a person to enter a name to say hello to, and we refuse to move forward until they do?

What we’re describing in each of these cases is a case of repetition; and we accomplish the process of repetition in programming by using a loop. For the following lessons, we’re going to set up another new project, this time called HelloLoopWorld. Make it part of the same solution, yet again, and make sure to set it to be the default project, using the drop-down menu next to the Start / Play button. If you need, go back and look at how we did this in the prior article – you should be able to do this in a fairly straight forward manner now.

After that, we’ll be ready to start diving into loops.

What is a loop?

There’s actually only a few things to discuss when it comes to the subject of loops. Essentially a loop is a block of code that repeats until some condition set is met or while some condition set is not met.

In some rare cases, a loop may actually be continuous. This is referred to as an infinite loop. In most cases, this is something that should be avoided; infinite loops can potentially cause a system to lock up, or to run out of available processing power or memory, leading to a crash of the computer. However, there are some instances in programming where such loops are necessary.

For our purposes, we’ll look at normal loops; those that are terminated by condition sets.

Loop Structures

Loops are generally accomplish with one of 3 general approaches: while loops, do-while loops, and for loops. Each of these approaches involves a key word or key words, with a set of brackets used to contain the code that is to be repeated. They key words will be accompanied with a set of conditions inside of a series of parenthesis, similar in many respects to the if statements we encountered in the prior lesson on conditions. In fact, the syntax within the while and do-while loop is identical in every respect to the conditional controls, because a loop’s translation is “if this condition is not met, do this again” or “if this condition still exists, do this again”. So when you have a handle on the if statement, you have a major portion of the while and do-while loops already figured out.

The other loop, the for loop, is a little bit more complex, but ultimately, the approach to coding with them can achieve the same thing. We’ll examine this in more depth later in this article.

It’s also good to note, there are a few other specialty case loops we’ll encounter in more advanced coding later on. A variation of the for loop, called the foreach loop, is found in more intricate programming methods. It’s not really any more difficult than the standard loops we’ll start with, but it requires some more elaborate data work to be of any significance to us.

Additionally, we’ll learn about a more sophisticated topic, RECURSION, which can be a bit tricky to get a handle on, but offers a LOT of valuable functionality with more advanced types of data.

In this lesson, we’ll discuss the FOR loop, but we’ll only do a serious implementation of using a WHILE or DO-WHILE loop. Seeing this form in use will give us a handle on the concept, and being aware that there are other approaches will suffice for a solid starting point.

While Loops

As stated before, loops are simply a method of repeating a set of instructions until some condition is met. And a “while” loop is as simple a loop as possible. The general structure of a while loop translates into “While this condition needs to be tested, do these instructions”. Here’s an example that will “count” to 10, taking a break each time.

//Created a "counter" integer and set it to 1
int i = 1;
while (i <= 10)
{
    Console.WriteLine("I am at {0}.  Press any key to continue", i);
    Console.ReadKey();
    i++;
}
Console.WriteLine("We have completed the loop.  The value of the incrementer is {0}", i);
Console.ReadKey();

You can put the code above into our Main method, and execute it. Each time a line is printed, you can press your enter key, until you see our final message. indicating the loop is completed.

So what happens is that we initiate an integer variable named “i” and set it equal to a value of 1. The next line indicates that we are creating a WHILE loop that will repeat while the value of “i” is less than or equal to 10. The loop consists of writing to the console the value of i, and instructs the user to press any key for the next step.

The method of print the message here is generating a sort of preformatted message. We are indicating that the line will print out message with a placeholder at {0}. By doing this, we can then substitute in a value, by adding that value at the end of the command, before the closing parenthesis. We could do similar things by printing a message like:

Console.WriteLine("This is variable 1 {0}, this is variable 2 {1}", var1, var2);

And the contents of var1 and var2 would get substituted into {0} and {1} respectively.

Back to the loop. We wait for the user to press any key, and then proceed on. In this case, we increment the value of i. Since it is a numeric value (specifically, a whole number) we can either write i = i + 1; or i++; Both of these accomplish the same thing – adding 1 to the current value in ‘i’. Then our condition in the while loop tests again. If the value of ‘i’ is less than or equal to 10, the process will repeat.

This brings up an important lesson as well. This test is happening before each set of instructions. In this case, we started with a value of 1. We print 1, then we increment to 2. The value is tested again, and is less than or equal to 10, so we print 2, increment to 3. Then the value is tested again, resulting in a 3, which is less than or equal to 10. So we print 3, and increment to 4. This continues through the point where we increment ‘i’ to 10. We do the test, and find that ‘i’ is less than or equal to 10, so we print 10, then increment again to 11. Now, the value of i is no longer less than or equal to 10. It’s 11. So we skip past the loop code, print out our “completed” message, and wait for a key press to end the program.

Now, what will happen if we put i++; BEFORE our ConsoleWriteLine to print out the value?

while (i <= 10)
{
    i++;
    Console.WriteLine("I am at {0}.  Press any key to continue", i);
    Console.ReadKey();
}

You can give it a try to see how the output changes; just make sure to restore our application to this before you move on. Our full application should look like this:

using System;

namespace HelloLoopWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            //Created a "counter" integer and set it to 1
            int i = 1;
            while (i <= 10)
            {
                Console.WriteLine("I am at {0}.  Press any key to continue", i);
                Console.ReadKey();
                i++;
            }
            Console.WriteLine("We have completed the loop.  The value of the incrementer is {0}", i);
            Console.ReadKey();
        }
    }
}

Do-While Loops

As mentioned before, the WHILE and DO-WHILE loops are fairly similar in nature. So if we wanted to write the above code with a DO-WHILE loop, the code would look like this:

//Create a new counter integer and set it to 1
int j = 1;
do
{
    Console.WriteLine("I am at {0}.  Press any key to continue", j);
    Console.ReadKey();
    j++;
}
while (j <= 10);
Console.WriteLine("We have completed the loop.  The value of the incrementer is {0}", j);
Console.ReadKey();

The code looks remarkably similar to the regular WHILE loop. In fact, the only major change is that we moved the “while” part to the end of our loop block, and ended it with a semi-colon, then put the word “do” before the loop block. The only other change of any sort is that we changed the name of the variable “i” to “j”, just so we could keep them distinct in the same program. If you put THIS into the application and run it, it’ll do the first set of repeats, then do the second set, and they’ll come out exactly the same.

So what is the point of having two different structures for the exact same thing? Well, the truth is, they’re not EXACTLY the same. to understand what I mean, change the lines for int i = 1; and int j = 1; to both have an initial value of “11”. Right now, the code will look like this (note that I commented the value of i for each integer so I know what the original value is supposed to be).

using System;

namespace HelloLoopWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            //Created a "counter" integer and set it to 1
            int i = 11; // normally set to 1 - changed to 11 for demonstration;
            while (i <= 10)
            {
                Console.WriteLine("I am at {0}.  Press any key to continue", i);
                Console.ReadKey();
                i++;
            }
            Console.WriteLine("We have completed the loop.  The value of the incrementer is {0}", i);
            Console.ReadKey();

            //Create a new counter integer and set it to 1
            int j = 11; // normally set to 1 - changed to 11 for demonstration;
            do
            {
                Console.WriteLine("I am at {0}.  Press any key to continue", j);
                Console.ReadKey();
                j++;
            }
            while (j <= 10);
            Console.WriteLine("We have completed the loop.  The value of the incrementer is {0}", j);
            Console.ReadKey();
        }
    }
}

Now, when you run the code again, you’ll get this:

Wait, the first loop skipped and just gave us the expected message of the incrementer being 11. The second one actually printed a message at 11 and then told us the incrementer as 12. What happened here?

The answer is fairly straight forward. If we initially ran through with the value started at 1, loop 1 would run through, and after i became a value greater than 10, it would skip the loop and print out the post-loop message. When we ran through the second loop in the same fashion, it would start at 1, print the messages through 10, and then when it was greater than 10, print the post-loop message.

When we changed the starting values to 11, the first loop immediately tested and found the value greater than 10, bypassed the loop entirely and went to the post-loop message. On the second loop, the value started at 11, and the message was printed, and then it was tested to see that the value was greater than 10, so it did not repeat.

The short version is, a WHILE loop tests before it ever executes the loop. DO-WHILE loops execute 1 time BEFORE the test is performed. So in summary, a WHILE loop will immediately test before it attempts to run through the looped instructions, and a DO-WHILE loop executes the instructions at least once BEFORE it attempts to test. If you want a piece of code to execute once before you test for some value, use a DO-WHILE loop.

Input Loop Demonstration

Let’s see if we can demonstrate the value of this a bit more. Create another new project called HelloLoopInputWorld. When the project is created, we’ll create some code in the Main method to demonstrate WHILE and DO-WHILE logic.

First, let’s create a variable called myName of type string. Then, use the console commands to request the user’s name, and to read in their input to our variable

string myName;

Console.WriteLine("What is your name?");
myName = Console.ReadLine();

Next, we need a loop to check the value of the input, and determine if it has been populated with a non-blank character.

while (myName.Trim().Equals(string.Empty))
{
    Console.WriteLine("You must enter a name.");
    myName = Console.ReadLine();
}

Finally, we can put in a post-loop command to say hello. And after that, add a ReadKey() command to hold position in the program until we’re done.

Console.WriteLine("Hello, {0}!", myName.Trim());

Console.ReadKey();

If you’ve written your code properly, you should have a program that looks like this; I’ve added comments to clarify each section in relation to the lesson.

using System;

namespace HelloLoopInputWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create Variable
            string myName;

            //Request user enter name
            Console.WriteLine("What is your name?");
            myName = Console.ReadLine();

            //Check if name is an empty string when trimmed, and repeat until it's not
            while (myName.Trim().Equals(string.Empty))
            {
                //Prompt user to re-enter their name
                Console.WriteLine("You must enter a name.");
                myName = Console.ReadLine();
            }

            //Post-loop response
            Console.WriteLine("Hello, {0}!", myName.Trim());

            //Wait for any key to end
            Console.ReadKey();
        }
    }
}

If you run the application a few times, you can test to see what’s happening with the logic. On the first run, enter a value, like your name, or even the word “Test” immediately when prompted. The application will never display the line about how “You must enter a name.” If you run it a second time and hit enter, or a few spaces followed by enter, you’ll notice that it keeps prompting the user until they put in an actual, acceptable value.

Now that we have done a WHILE loop this way, let’s make a DO-WHILE loop as well. We can use the same project for this. After the Post-loop response, but but before the final Console.ReadKey() command, add in a few blank lines.

We can re-use the myName variable since we don’t need to preserve that information for anything else. However, we’ll set the variable to NULL. NULL is a value that means that the myString is set to non-existence, which is actually different from saying it exists, but is empty. Doing this is as simple as sying “myName = null;” Create a DO-WHILE loop, and make the condition the exact same as it was in the WHILE loop. After the loop, we can place our message to print out the name, exactly as we did for the WHILE loop.

//Set myName to non-existent value
myName = null;

//DO WHILE loop
do
{
    //REPEATED CODE IN HERE
}
while (myName.Trim().Equals(string.Empty));

//Post-loop response
Console.WriteLine("Hello, {0}!", myName.Trim());

Now there are a number of ways we could handle getting the data from the user and printing responses. We can have the input read into the variable, and if the input is empty, print out a message. We could use a condition to check if this method is a repeat. and if it isn’t provide a different message. We could do an IF-ELSE approach to checking for what was put in. The truth is, there’s no single way to do it that’s necessarily “better” than another, so long as we keep it as simple as we can.

In this case, since I have already set the value of the variable to NULL before the loop starts, I can use a check on that to change the message that comes out inside the loop. Like so:

//REPEATED CODE IN HERE
if (myName != null)
{
  Console.Write("You didn't enter a name. ");
}
Console.WriteLine("Please enter your name.");
myName = Console.ReadLine();

The entire program should now look like this:

using System;

namespace HelloLoopInputWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create Variable
            string myName;

            //Request user enter name
            Console.WriteLine("What is your name?");
            myName = Console.ReadLine();

            //Check if name is an empty string when trimmed, and repeat until it's not
            while (myName.Trim().Equals(string.Empty))
            {
                //Prompt user to re-enter their name
                Console.WriteLine("You must enter a name.");
                myName = Console.ReadLine();
            }

            //Post-loop response
            Console.WriteLine("Hello, {0}!", myName.Trim());

            //Set myName to non-existent value
            myName = null;

            //DO WHILE loop
            do
            {
                //REPEATED CODE IN HERE
                if (myName != null)
                {
                    Console.Write("You didn't enter a name. ");
                }
                Console.WriteLine("Please enter your name.");
                myName = Console.ReadLine();
            }
            while (myName.Trim().Equals(string.Empty));

            //Post-loop response
            Console.WriteLine("Hello, {0}!", myName.Trim());

            //Wait for any key to end
            Console.ReadKey();
        }
    }
}

If you’ve put together your code properly, when you run it, you’ll be prompted for your name, and then get a response. Then it’ll prompt for your name again. The new approach will Tell you that you didn’t enter a name, and prompt you again, repeating this until there is a non-emtpy, non-null value.

For Loops

FOR loops aren’t really a drastic difference from the WHILE / DO-WHILE loop logic; in general they can accomplish many similar things. Though there are a few, small, key differences in how they work and are used. First, let’s talk about the setup.

FOR loop controls typically consist of 3 pieces of logic: initialization, condition test, and iteration. So rather than having to create an initial value on one line of code, then do a loop for testing that condition on another line of code, and having a place where logic increments a value like a counter on a third line, we can do them all in one comprehensive step. So for example, if we wanted a simple counting loop like so:

int i = 0;
while (i < 100)
{
    Console.WriteLine ("Loop value {0}", i);
    i++;
}

We can instead combine all of these into

for (int i = 0; i < 100; i++)
{
    Console.WriteLine("Loop value {0}", i);
}

These example will produce the same exact code; but there are differences in what a WHILE and FOR loop do to accomplish things. First, in a WHILE loop, the actual iteration (in this case, the incremental increase of an integer) happens as part of the body of the loop, where as in the FOR loop, it’s a part of the loop structure itself. This means that in a WHILE loop, you’re responsible for that step at some point in the logic of the body of the loop itself.

Second, in FOR loops, the logic of the iteration happens after the body of the loop is created, and can not be skipped in any fashion; it’ll be precisely the same increment at each step. In a WHILE loop, however, we can use conditions to change what happens in each loop cycle; we can use this to prevent iteration, or iterate by more than a default value.

Finally, if you write a FOR loop without a condition to test, you can lead to an infinite loop; you might desire this, but you do need to be careful of the impact of such code. Meanwhile, in a WHILE loop, you MUST have a condition to test, or you application will not build.

It’s not uncommon to hear people say that for loops are best when you know a select number of iterations that will be needed for a loop, and while loops are best used for instances where you don’t know what the number of repeats will be, but that’s not entirely true. Most types of iterative objects (objects that can be looped through) provide a mechanism to get the size, or length or some other value indicating the maximum number of times to iterate through something, so in most cases, this isn’t a concern, strictly speaking.

And in most cases, you can actually go with either approach. Realistically, the alternate logic for iterations is probably the most important aspect of such logic. This will become more obvious in later lessons when we work with more advanced data structures. For now, seeing the different approaches is the most important lesson to be learned.

Conclusion

As we wrap up this lesson on the fundamentals of loops and looping, you might wonder why it is that we didn’t do any more detailed examples than what we have so far. We really didn’t implement an example of a FOR loop in a project, we didn’t really do a whole lot with even the WHILE or DO-WHILE loops.

The reason is that we have a few more things we’ll need to cover to make more effective use of these logical blocks. We could write a simple demonstration, and that would be all well and good, but it would be a LOT of work to set up static loops to accomplish very little of value. The next lesson we’ll have will introduce us to working with OBJECTS, and a further lesson will expand on that topic. When we’ve done both of those things, we’ll have more information and have a better use for the techniques of looping.