Week 2
Introducing Loops

An old CS joke. Why did the Computer Science student starve to death in the shower? He was following the instructions on the bottle of shampoo. To really "get" the joke, you have to learn about iteration, a Computer Science term that means repeating a set of actions. Iteration is also called repetition or looping. The statements that are used in iteration are called loops. Let's start by comparing iteration to the if statement.

Both iteration and selection are flow-of-control statements; they control which code is executed inside your program.

  • Like the if statement, iteration is based upon evaluating a Boolean—true/false—condition, and then performing a set of actions if the test is true, and skipping them if it is false.
  • Both loops and if statements have a condition part, (the test), and a body part, (the actions that are taken).
Illustrating the difference between loops and if statements.

Selection works like the illustration on the left. Driving down a highway, you come to a rest stop pull off. When you leave, you rejoin the highway further down the road. Once you rejoin the highway, you have no opportunity to go back, and revisit the rest stop again. Those who bypass the turnoff, skip the rest stop altogether.

A loop looks similar, but it not the same. The illustration on the right shows that there is still a test, but, after you've had your break, the exit road "loops back" (hence the name), and you rejoin the highway where you initially left it. If you like, you can choose to enter the rest stop once again, even though the highway is one-way. In this sense, a loop works a little like a cloverleaf interchange.

Week 2

Guarded & Unguarded Loops

C++ has four loops:

while (condition){ statements; }
do{ statements;} while (condition);
for (initializer; condition; update){ statements};
for (element : collection){ statements;}

Each loop is designed for a particular purpose, and each has a place where it is most effective. One difference is where the test takes place.

Test at the top and test at the bottom loops.

The do-while loop, illustrated on the right loop, tests its condition after it has performed the actions in the loop body at least once. This "test at the bottom" loop is also called an unguarded loop, because it "leaps before it looks".

The others three loop types check the test condtion before performing the actions in the loop body. These are called guarded loops, because when the test condition is false, then the actions inside the loop body are never performed at all.

Week 2
Guarded & Unguarded Loops

Classifying loops according to where their condition is tested is not really very useful when it comes to deciding which loop to use. It is much more useful to classify loops by the kind of bounds that they employ.

A loop's bounds are the conditions under which it will repeat its actions. In a simple, loop, the this might be expressed as "the counter has a value less than ten". In more complex loops, the bounds may be a combination of conditions. There are three major kinds of loops that can be built using the basic loop syntax available in C++.

  • A definite or (counter-controlled) loop repeats its actions a fixed number of times—a "gimme fifty pushups" kind of loop. Ideally you can read the code and tell how many times the loop will run.

    Sometimes you won't know the exact number of repetitions until runtime; it may be based upon the number of characters in a string, for instance, or some other number which is not computed until then.

  • With an indefinite loop you can never tell how many times the loop will repeat by examining the code. An indefinite loop is a loop that tests for the occurrence of a particular event, not a count of the number of repetitions.

    "Read characters until you encounter a period" is an indefinite loop. The bounds may be reached after reading three characters, or, after reading three-thousand. It's also possible that the period might be the first character or might not occur at all.

  • Range-based loops were added to the language in C++11. Range loops iterate over a collection of elements, such as a string, array or vector. The informal name for a range loop is a foreach loop. The range-based for loop looks like this:

    for (declaration : collection)
        statement

    where collection is an object of a type that represents a sequence (such as a string), and declaration defines the variable that is used to access the underlying elements in the sequence. On each cycle of the loop, the variable in declaration is initialized from the value of the next element in collection.

    Now, let's look at different kinds of indefinite loops.

Week 2

Indefinite Loop Categories

Indefinite loops are those that wait until an event occurs at runtime to complete. You might wonder, "what kind of event could that be?". Here are three kinds of indefinite bounds; each uses a different sort of bounds:

Data bound loops are those that keep reading from input until there is no more data to be read. Data loops are used when processing files or network data. We'll work extensively with data loops when we get to streams.

Here is an indefinite data loop that reads all of the words from a file, represented by the input file object named in, and prints each one on its own line:

string word;
while (in >> word)
{
    cout << word << endl;
}

Sentinel bound loops look for the presence of a special value, contained within its input, to determine when to quit. If your problem is "read characters until you encounter a period", then the period is the sentinel.

Sentinel loops are often used in searching, but have other uses as well. This sentinel loop finds the position of the first period entered.

int position = 0; char c;
cin >> c;
while (c != '.') // Loop sentinel
{
    position++;
    cin >> c;
}

Limit bound loops end when another repetition of the loop won't get you any closer to your goal. They are often used in scientific calculations and other numeric algorithms, when stating a precise termination condition is not possible.

Often this involves monitoring the difference between two variables, and stopping the loop when the difference passes a predetermined threshold. Here is a limit-loop example which counts the number of odd digits in an integer n:

int count = 0;
while (n != 0) // Loop limit
{
    if (n % 10 % 2 == 1) { count++;} 
    n = n / 10;
}
Week 2

Range-based Loops

As mentioned earlier, range-based loops were added in C++11. A range loop will visit each element in a collection, setting the range variable to each value in the collection, in turn. These loops are very similar to the simplified for loop added in Java 5, and the for in loops in Python.

Let's look at the three variations of range-based loops which are offered in C++. We'll start with value iteration, which is the closest to the version used in Java.

Here's a short example, which prints each character in a string on a line by itself:

string snakeOuroboros;
for (char c : snake)
{
    cout << c << endl;
}

On each loop cycle, the variable c is initialized with a copy of the next character in the string snake. When all of the characters have been processed, the loop stops. Thus, you can read this loop as saying "for each character in snake, do something".

With value iteration, changes to the variable c have no effect on the string snake. If you want to change the string itself, then use reference iteration. Here's a second example which does that:

string str{"one two three"};
for (char& c : str)
{
    if (c == ' ') { c == '_';} 
}
cout << str << endl;

Finally, if the items you are iterating over are very large, and you want to make sure you don't change them, then you'd use const-ref iteration like this (made up) example.

Album photos(get_phone_photos());
for (const Image& img : photos)
{
    if (is_cute_cat(img))
   { 
        display(img);
   } 
}

Because each picture in your photos library might be very large, you wouldn't want to copy them with value iteration. Similarly, since you wouldn't want the CuteCats app to have the ability to modify (or perhaps erase) your cute cat photos, the loop should access each variable as a const Image&.