Introduction to Computer Science - C++

Loops - Repeating the same action more than once

We have seen that to get a computer to do what we want we must tell it every step, down to the last detail. This can be very tedious.   It is especially tedious when we want it to do the same action several times.   For example in the first chapter we wrote a recipe for a computer to mix a cake. We wrote "stir contents of bowl with mixing spoon 10 times". Normally, to get the computer to do this we would need 10 instructions; one for each stir. Wouldn't it be nice if we could tell the computer to repeat the previous action 9 more times? Then we could save some typing. This would be really useful especially if we had wanted the computer to stir the bowl a hundred times.

So how do we tell the computer to repeat an action many times? In the early days of computer programming, programmers would have the computer jump from place to place in the code. If you remember, programs normally execute in a downward sequence. Using the goto command programmers could force the computer to go back up when needed. Programming in this way was soon discovered to be confusing and inefficient. This method has since been replaced with a more structured method. Nevertheless, I will start by demonstrating the use of goto before I go on to explain the newer methods. So bear in mind that using goto is strongly discouraged.

The goto command works together with a label which acts as a bookmark. I first must label a certain place in my code and then I can goto that place. Here is an example:

top:
    cout << "Hello world!" << endl;
    goto top; 
The computer will begin reading these lines top down. When it sees the line top: it will simply register the label called "top" as being at this point in the code, but this line will have no other affect on the program. Notice that this line ends in a colon ( : ) not a semi-colon (;). The label can be any valid identifier, not necessarily the word top!

After this line, the computer will go on to the next line and print Hello world! to the screen one time. Then the computer will read the line

goto top; This will cause the computer to jump up to the line labeled top: and continue reading down from there. Obviously, this will cause the computer to print Hello world! over and over again infinitely. This could crash your computer, so don't try this example. This example has created what is called an infinite loop. It is called a loop because the computer loops back to the top each time it finishes a certain section. It is call inifinite because it never ends. Infinite loops should always be created with a built-in way to end them, otherwise they will eat up all the processing power of your computer and may cause a crash.

We can add a built-in method of ending the loop by adding a user interface to this code segment. The user interface will allow the user to end the loop by entering an integer, for example 0. Here is how I might do this:

bool end = 1;
top:
    cout << "Hello world!" << endl;
    cout << "Press 0 to end loop, 1 to continue." << endl;
    cin >> end; 
    if (end != 0)
       { 
       goto top;
       } 

Notice how I initialized the variable end with the value 1. Then I allow the user to change end's value to 0 if he desires to end the loop. Then I check if end is not equal to 0. If it is not equal to 0, I continue the loop by jumping or looping back to the top of the code section where I want the loop to start. Notice I do not loop over the initialization of end because I only need to do this line once. In addition to the initialization, the other essential part of the loop is the test condition or as it is properly called the continue condition. It is the condition by which the loop will continue looping. In this case the continue condition is

if (end != 0) Notice also that in this example if the user types any non-zero value, the loop will continue.

In the previous example, we allowed the user to decide when the loop will end, but sometimes we want to decide from the start how many times our loop will loop. The way this is done in general is by setting a variable to count for us. We can then repeat our action until our counter reaches some limit of our choosing. For example, if we want to do something 10 times we could set a counter to zero, and then do our action and up our counter by 1. Upping the counter by one is called incrementing the counter by one. It's called incrementing because we add the same small increment to the variable each time we loop.

Once the counter reaches 10 we know it is time to quit. You may notice that I decided to start the counter at zero, not one. This is the usual way of doing things in C++, but you could also start your counter at 1. Let's see this example first in pseudo-code and then in C++.

make a variable and call it "counter"
assign the value "0" to the "counter"
do the following
add "1" to counter
write this message to the screen "Hi mom!"
repeat as long as counter is less than "10"

In the above pseudo-code I gave the name "counter" to the variable, but I could have given any other name just as well.   I could have called it "George", but I like to give names that mean what the variable is used for. Since this variable is supposed to count, I called it "counter." In trying to understand the logic of the above instructions ask yourself, How many times will the message "Hi mom!" get printed? Now let's see how to implement the pseudo-code in C++. Try to match up each line of pseudo-code above with the C++ below.
int counter;
counter = 0;
startloop:

counter = counter+1;
cout << "Hi mom!" << endl;
if (counter < 10)
{
goto startloop;
}

Can you match up the two versions?   Try again!   OK, my turn to tackle this code. One thing should confuse you, what does this line mean:
"counter = counter+1;"?   How can a variable equal the same variable plus 1?     That breaks the rules of algebra!   If counter is 1, well, 1 does not equal 1 + 1!   What is our mistake?     Our mistake is that we think = means equals, remember it means assign the value on the right side to the left side.   In our case that translates to assign the value 1 + 1 to counter.   Counter had been 1, now it will be 2. Another way of thinking about what this line means is to translate it as follows: "the new value of counter will now be what the old value of counter was, plus one." Think about this for a moment. In my experience many people forget this point (if they ever really understood it in the first place.) In any case, this is how we increment the counter, as I explained above.

Using goto is a good way to understand how looping works, but it can get confusing especially if you have several labels. Instead of using goto we will use structured loops to create loops.

The basic structured loop is the while loop. The while loop is designed to continue some action while some condition is true. Once the condition is no longer true the while loop stops repeating. In the above example, we created the looping affect by combining the if with the goto statement. The while loop is a built-in way of combining the if with the goto. Here is the basic structure:

while ( continue condition )
{
block of code

}

As  long as the continue condition is true, whatever is inside the braces will be repeated.  As we learned earlier,  I can write as many lines of code inside the braces and it will all be considered one block of code.  Then this entire block of code will be repeated while the continue condition is true.  Let's see the previous goto  example rewritten as a while loop.

int counter;
counter = 0;
while ( counter < 10 )
{ counter = counter+1;
cout <<"Hi mom!"<<endl;
}

When the computer comes to the while keyword, it checks, is the condition true. If that condition is not true, then it skips over the block of code inside the braces, just like in an if statement, and continues to execute the code after the close brace } (in this example there is no code after the close brace, so the program would end).  If, on the other hand, that condition is true then the computer begins to execute the code inside the braces { }.  After the computer executes the last line inside the braces, it then comes to the closing brace }. When it sees the closing brace, it knows to jump back up to the continue condition inside the while statement.  It then re-evaluates the condition and either skips or executes the block of code depending on whether the continue condition is false or true still. If the continue condition were always true, then the loop would be an infinite loop and never end. To avoid this, make sure that a variable inside the block of code is changing on each execution of the loop. In this way, eventually, the condition will be false.

In this example, the continue condition is true from the start but each subsequent loop brings counter closer to 10. When counter eventually reaches 10, the condition will be false.  At that point the computer will skip the block of code and continue executing from after the close brace }. In this case, the program would finish at this point.

Some people confuse the while loop with the if statement. They are similar insofar as they both test a condition and either skip or execute the following block of code depending on whether the condition is false or true.  But, the difference between  while and if is that in and if statement the condition is evaluated only once and the block of code is executed at most one time.  The while has the ability to repeat code by jumping up to the top again in a kind of looping effect.

Incrementing with ++

In the above example we used a variable called counter and we incremented it (that is, we increased its value by one each time the loop executed). Incrementing counters or any variables is a common part of programming. Therefore, the creator of C++ made a shorter way to increment variables. Instead of writing

counter = counter +1;

You can simply write:
counter++;

The ++ operator (called the increment operator) is used to increase the value of the variable by one. Some people get confused and try writing
counter +1;

This will in no way affect the value of counter. It is an error. So remember, if you want to write counter=counter+1, just write counter++.

If you would want to increase your counter by, say, 2 for example, you would write

counter = counter +2;

But there is also a shorthand way to write this. Just write:
counter += 2;

So too you can decrease or decrement your variable by one like this:
counter--;

The same sort of shorthand versions of incrementing exist for the other mathematical operators also. Here is a table of some examples of incrementing and decrementing possibilities:
Long version Short version
i=i+1 i++
i=i+7 i+=7
i=i-1 i--
i=i-2 i-=2
i=i*8 i*=8
i=i/2 i/=2

Note that in all these examples, the value of i is actually changed.

There is also an alternate version of the ++ and -- operators. What you have see thus far has been of the form

variable++;
You can also increment or decrement by writing
++variable;
Or
--variable;
How is this different from what we did previously? In the new version the incrementing or decrementing happens sooner. For example, the following code segment would print the number 8
int var1, var2;
var1=8;
var2=var1++;
cout <<var2;
This prints 8 and not 9 because the assignment to var2 happens before the incrementation of var1. If you want to force the incrememtation to happen first, you must write it like this:
int var1, var2;
var1=8;
var2=++var1;
cout <<var2;
The same is true for the -- operator. There is a simple way to remember this difference. If the ++ or -- operator appears before the variable, then the incrementation or decrementation happens before everything else. If it appears after the variable, then the incrementation or decrementation happens afterward.

More kinds of loops

We have now seen the most basic type of loop, the while loop. In truth, if you need to create a loop, all you ever really have to use is this loop. But two other loop structures exist in C++ and they are designed to be used in certain common cases.

Sometimes you may want to do a loop once no matter what and only check the continue condition statement afterward to decide whether to do the loop a second time. A classic example of this need, the need to skip the first-time condition check, is when you are printing a menu for the user. In a classic menu you want to print a series of choices for the user and then check what his response is. So we need to do the action and then check the continue condition.

I will show you the basic structure of this kind of loop and then a menu example. The loop is called a do while loop. Here is the structure:

do {
 code block 

} while ( continue condition ) ;

So you see it is rather like the while loop , but in this case, the word while comes at the end. Be careful to remember the semi-colon ; at the end of the continue condition. What this structure does is execute the code block once and then test the continue condition. If the condition is true, then the code block is executed a second time, and so on.

Now let's see an example. Here is the menu example I promised:

int input;
do {
cout << "Please enter any positive integer, (-1 to quit)" << endl;
cin >> input;
cout << "You entered a " << input << endl;
}while(input != -1);

When this loop runs, it will output something like this


Please enter any positive integer, (-1 to quit)
5
You entered a 5
Please enter any positive integer, (-1 to quit)
-1
You entered a -1

If I had used a while loop, I would have had to repeat code like this:

int input;
cout << "Please enter any positive integer, (-1 to quit)" << endl;
cin >> input;
cout << "You entered a " << input << endl;
while(input != -1)
{
cout << "Please enter any positive integer, (-1 to quit)" << endl;
cin >> input;
cout << "You entered a " << input << endl;
}

I think the do while version is more concise and more clear. It has also saved me some typing and potential confusions.

There is another kind of loop, the for loop. It has the advantage of compactly structuring the common commands needed for creating a loop based on a counter. Use a for loop when you know ahead of time exactly how many times you will be doing some set of actions. You will need to use and initialize a counter. Here is the structure:

for  ( counter initialization ; continue condition ; counter incrementation )
{

 code block 

}

You will note that there are three sections inside the parenthesis of the for statement. They are separated by semi-colons ; . The for loop requires exactly two semicolons always. These two semicolons create three sections inside the parenthesis immediately following the word for. Any and all of these sections can be left blank. But more often you will write something in them. What you can write depends on which section you are writing in. The first section is called the initialization section. It is for setting the counter(s) you plan to use. You can also declare variables in the initalization section. The second section is called the continue condition section. It is use to set the condition by which the loop will either continue looping (iterating) or stop looping. It is the same as the continue condition of the while and do while loops. The third section is called the incrementation section. It is pretty much used for incrementing the counter, for example you may write i++ or counter++, but actually you can do just about any command here. In general, just use the incrementation section for incrememting your counter(s).

If you want to do two or more initializations or incrementations, simply separate them by commas within the relevant section. You cannot have more than one condition, but you can create complex conditions just as you can with if. So too, you can have complex conditions in the while and do while loops. Here is a basic example of a for loop (note the use of the three sections):

for ( int i = 0; i < 10 ; i++)
{
cout<<"5 times " << i <<" is " << i * 5<<endl;
}

The output of the above would be

5 times 0 is 0
5 times 1 is 5
5 times 2 is 10
5 times 3 is 15
5 times 4 is 20
5 times 5 is 25
5 times 6 is 30
5 times 7 is 35
5 times 8 is 40
5 times 9 is 45

Some other for loop possibilities are:
for ( int i = 0, int j=10 ; i < 10 && j < 100 ; i++ , j*=2) // two counters, double condition, double incrementation
for ( i = 0, j=10 ; i < 10 ; i++ , j--) // two counters, one condition
for ( i = 0 ;;) //no condition, infinite loop
for (;;) // infinite loop

You can see that the for loop allows us to include a lot of information in a concise and clear format. The for is a powerful type of loop that you can use regularly. You can use the more simple while or do while loops when you need to repeat some action an indefinite number of times.

Nested Loops

We saw that if structures can be placed one inside the other. We called this nested ifs. The same can be done with loops. We can place a loop within another loop. We then have an inner loop and an outer loop. Doing this we create what are called nested loops. Many complex programming exercises require nesting loops. For now I will stick to some simple examples. Here is an example:

for (int i = 2 ; i < 4; i++)
{
  for (int j = 2; j < 7; j+=2 )
     {
     cout<<i<<'*'<<j<<'='<<i*j;
     cout<<endl;   
     }
}
This will produce the following results:
2*2=4
2*4=8
2*6=12
3*2=6
3*4=12
3*6=18

The following example will print this:

1.  1,2,3
2.  4,5,6
3.  7,8,9
Here is the example:
int number = 1;
for (int i =1; i < 4; i++)
{
  cout<<i<<'.';
  for (int j =1; j < 4; j++ )
     {
     cout<<number<<',';
     number++;
     }
  cout<<endl;   
}

This example may take you some time to understand. As you can see nested for loops can get pretty complicated. What you need to do is sit with a pen and paper and write down all the variables and keep track of how they change as the loops progress. Trying to do this in your head is asking for trouble and even experienced programmers need to resort to pen and paper when faced with complex problems such as these.

Some more example programs.

Flags

Sometimes I have a loop which can end for one of several reasons. In such a case I can use flag to indicate why the loop ended. A flag is a variable whose whole purpose is to indicate if a certain event has happened. A flag is a programming concept which can be implemented in any language. It is not specific to C++ nor is flag a reserved word. One place where I could use a flag is when, for example, I have a loop to let a person try to guess a certain number. The loop will end after 5 guesses or if he guesses the right number, which ever comes first. So how will I know why the loop ended? I can set a flag for this purpose.

int number = 75;
int guess;
bool gotItRight = false; // this is my flag
for (int i =0; i < 5; i++)
{
 cout<<"What number am I thinking of?" <<endl;
 cin >> guess; 
 if (guess == number)
        {
          break;
	  gotItRight = true;
	}
}

 if (gotItRight)
     cout<<"You got it right!!" <<endl;
 else
     cout<<"No more guesses, better luck next time." <<endl;

Notice that the flag "gotItRight" will only be true if he guessed the right number. If the loop ends without his guessing the number, goItRight will still be false. There are obviously other ways to accomplish this result but using a flag is one way. Probably no program ever needs a flag, but sometimes they are convenient. But in general, try not to use flags. Never call a flag "flag". Give a flag a meaningful name, usually composed of a verb and noun.

Exercises:

  1. Use goto to write a program in which the user must guess the right number, as stored in a variable in the program. If he guesses two low, tell him he guessed too low and give him another guess. If he guesses two high, tell him he guessed too high and give him another guess. Repeat this until he has guessed the right number.
  2. Write a calculator which allows for + - * / = and allows the user to enter 2 numbers and computes the result. Use a while loop to permit him to continue using the calculator until he types # to quit.
  3. Write a while loop to print out the even numbers from 1 to 20 inclusive.
  4. Use a while loop to allow a teacher to enter as many grades as he wants for a given student. When the teacher finishes entering the grades, compute the arithmetic mean of the grades.
  5. Using only a cout<<'*'; a cout<<' '; and a cout<<endl; print a triangle made out of stars (*) in the following formats. Allow the user to tell you how many rows of stars to make. The stars should create a triangle shape. For example, if the user asked for 5 rows, you should print this:
        *      *****      *  *****       
        **     ****      **   ****
        ***    ***      ***    ***
        ****   **      ****     **
        *****  *      *****      *
    
  6. Use a set of nested while loops to print the 12 times tables. Print it in a table form, i.e. rows and columns.
  7. Use a for loop to create a list of the mulitples of 3 from 0 to 300.
  8. Write a program with a user interface which allows the user to enter a number. Then print for him all the factors (divisors) of that number. See wikipedia.org for an explanation of what a factor is.
  9. Write a program for printing a check's numerical dollar amount in a safeguarded format like this *****122.00 Maximally there can only be 10 digits and a period. The user should input a floating point variable and your program should add following zeros or truncate extra decimal point values. Also any unoccupied leading places should be filled with asterisks.
  10. Use nested for loops to compute pythagorian triples where the third number remains less than 200. Pythagorian triples are whole numbers where the sum of the squares of the first numbers equals the square of the third number. For example, 3,4, and 5 are a pythagorian triple because 32 (9) + 42 (16) = 52(25). Be sure to remove triples which are multiples of previous triples.
  11. Write a calculater which is capable of multiplication division addition subtraction and powers but use only the + and - operators. Do not use the * and / operators. You will need to use loops to calculate your answers.
  12. *** Using only a cout<<'*'; a cout<<' '; and a cout<<endl; print a diamond made out of stars (*). Allow the user to tell you how many rows of stars to make. The stars should create a diamond shape. For example, if the user asked for 5 rows, you should print something like this:
          *
         ***
        *****
         ***
          *
    
  13. Write a program which accepts a binary number ( an unsigned integer containing only 0s and 1s) and prints its decimal equivalent.
  14. Write a program which accepts an unsigned integer and prints it factorial. The factorial of a number, n is written n! and is equal to n * (n-1) * (n-2) *...*1
  15. Write a program which accepts a six digit unsigned integer and prints "true" if the number is a palindrome or "false" if it is not. A palindrome is a number which when read from left to right or right to left is the same. For example 15551 is a palindrome.
  16. Write a program which sums a sequence of integers. When the number zero is entered it indicates that no more numbers are to be summed. Print out the total sum.
  17. write a program that finds the largest of several integers. the first integer read indicates how many integers will be read. do not use the first integer as one of the numbers to be compared.
  18. Write a program that reads 6 unsigned integers and produces rows of asterisks according to the numbers entered. For example if one of the numbers is a 7 then print *******.
  19. Calculate the value of Pi from the infinite series
    Pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...
    Ask the user how many terms of the series he wants to use to calculate Pi and produce the correct result for him.

Terms to remember

got , label , loop, infinite loop, incrementation, counter, while, block of code, increment operator ++, decrement operator --, do while, for
 

fibonacci etc.

© Nachum Danzig September 2006