Notes for Oct 28

For loop

Previously we looked at a while loop to count through some integers:

int n = 1;
while(n <= 10)
{
    cout << n << endl;
    n++;
}

Many loops have this similar structure: there is an initializer (int n = 1;), a test expression (n <= 10), and an update statement (n++;) at the end of the loop body.

To accommodate this common structure, C offers a for loop. The syntax is that there are three distinct things within the parentheses, separated by semi-colons:

for(INITIALIZE ; TEST ; UPDATE)
{
    BODY...;
}

So, rewriting the above counter loop into the for syntax, we have:

for(int n = 1; n <= 10; n++)
{
    cout << n << endl;
}

This is nice because all the stuff that controls the loop is in one place, rather than scattered onto different lines like in the while loop.

It’s fine to leave any part of the for structure blank, but it always needs both semi-colons. So if you prefer to initialize the variable above the loop, this works too:

int n = 1;
for(  ; n <= 10; n++)
{
    cout << n << endl;
}

Do loop

There is another variant of the while loop, called a do loop, or sometimes “do-while.” It looks like this:

do {
    BODY...;
} while(TEST EXPRESSION)

The main difference is that the test expression is checked after executing the body each time, rather than before executing each time. That means that the body of a do loop will always execute at least once.

You might think that the do loop would be useful for input validation. Here’s an example of an input validation loop using a regular while:

int num;
cout << "Enter number 1-5: ";
cin >> num;
while(n < 1 || n > 5)
{
    cout << "ERROR\n";
    cout << "Enter number 1-5: ";
    cin >> num;
}

That works fine, but it’s unfortunate we have to duplicate the cout/cin lines. Can we do better with a do loop?

int num;
do {
    cout << "Enter number 1-5: ";
    cin >> num;
} while(n < 1 || n > 5)

This works okay if we don’t need to put an error message – it repeatedly asks until we get it right. But adding a condition for that error message duplicates the test expression:

int num;
do {
    cout << "Enter number 1-5: ";
    cin >> num;
    if(n < 1 || n > 5) {
        cout << "ERROR\n";
    }
} while(n < 1 || n > 5)

Blecch. So the solution to this (although some might argue against it) is actually to create a would-be infinite loop, but then “break” out of the middle of it:

int num;
while(true)
{
    cout << "Enter number 1-5: ";
    cin >> num;
    if(n >= 1 && n <= 5) {
        break;
    }
    cout << "ERROR\n";
}