Loops

Much computing is repetitive work. Evaluate an expression many times with different values. Read lines of a file. Update a large number of variables. To accomplish this, we use loops.

Loops may invoke other loops as part of their bodies. These are generally called nested loops. Nested loops can result in many millions of executions of statements, so some care may be required in their construction to avoid unnecessary repetitions.

For Loops

The for loop executes a fixed number of iterations unless explicitly terminated. It is most generally expressed as

for ( initializer; stop condition; increment ) {
    code;
}

Starting from the initializer statement, the “stop condition” is evaluated. If it is false the flow continues to the body of the loop. If it is true, the loop is exited without executing any of the statements in the body.

One of the most common forms employs integer loop variables.

for (int i=l;i<=u;i+=s) {
  code;
}
  • i: Loop variable
  • l: Lower bound
  • u: Upper bound
  • s: Stride, or increment. Usually we use i++ for a stride of 1.
    • s can be negative, in which case l must be greater than u. For an increment of -1 use i--.

Do not change the loop variable within a loop. That is, it should not appear on the left-hand side of an assignment.

There is a subtle difference between

int i;
for (i=0;i<10;i++) {
    std::cout<<i<<"\n";
}

versus

for (int i=0;i<10;i++) {
    std::cout<<i<<"\n";
}

In the first case, i is in scope within and beyond the loop. In the second case, i is in scope only within the loop. Try the example:

#include <iostream>

int main() {

   int i;

   for (i=0;i<10;++i) {
       std::cout<<"I is "<<i<<"\n";
   }

   std::cout<<"Outside the loop I is "<<i<<"\n";

   for (int j=0;j<10;++j) {
       std::cout<<"J is "<<j<<"\n";
   }

   //std::cout<<"Outside the loop J is "<<j<<"\n";

}

Uncomment the line to print j after the second loop and try it again. What happened? To the compiler, the variable j literally does not exist outside the loop.

We will discuss scope in more detail later.

Range-Based For Loops

The C++11 standard has introduced a new version of the for loop that may be familiar to programmers of Python and similar languages. This loop steps through an iterator. An iterator is a sequence that can be traversed in a unique order. The only iterator we have encountered so far is the string. For example, we can loop over a string and extract each character:

#include <iostream>
#include <string>

int main() {

   std::string greeting="Hello Everybody";

   for (char s :greeting) {
       std::cout<<s<<" ";
   }

   std::cout<<"\n";

   return 0;

}

While Loops

Whereas for loops execute a particular number of iterations, while loops iterate based on the truth or falsity of an expression. The while continues as long as the expression is true and terminates when it becomes false. It is up to the programmer to be sure to add statements to ensure that the expression eventually evaluates to false so the loop will end.

while (boolean expression) {
   statement;
   statement;
   statement somewhere to check expression;
}

Example:

#include <iostream>

int main() {

    int x, y, z;

    x=-20;
    y=-10;

    while (x<0 && y<0) {
        x=10-y;
        y+=1;
        z=0;
    }
    z=1;

    std::cout<<x<<" "<<y<<" "<<z<<"\n";

}


Do While

The standard for and while loops test at the top. That is, upon entry to the loop, the termination condition is evaluated. If it is false, the statements of the loop are executed. Otherwise the loop is exited. With the ability to break out of the loop at will, we can change this pattern. C++ provides a do while construct for this.

do {
   statement;
   statement;
   while (boolean expression);
}

A standard while loop may not be entered if the condition is initially false, whereas a do-while will always be executed at least once.

#include <iostream>
#include <sstream>
#include <string>

int main() {

    std::string num_in;
    float number;

    do {
        std::cout<<"Please enter a number. -999 to stop.\n";
        std::cin>>num_in;
        std::stringstream ss(num_in);
        ss>>number;
        std::cout<<"You entered "<<number<<std::endl;
    } while (number!=-999);

    return 0;

}
    

Exiting Early and Skipping Statements

The break statement leaves the loop immediately. A break is able to break out of only the loop level in which it appears. It cannot break from an inner loop all the way out of a nested set of loops. This is a case where goto is better than the alternatives.

The continue statement skips the rest of loop and goes to the next iteration. Like break, it applies only to the loop level in which it is located.

x=1.;
while (x>0.0) {
    x+=1.;
    if (x>=10000.0) break;
    if (x<100.0) continue;
    x+=20.0;
}

Exercises

  1. Loop from 0 to 20 by increments of 2. Make sure that 20 is included. Print the loop variable at each iteration.
  2. Start a variable n at 1. As long as n is less than 121, do the following:
    • If n is even, add 3
    • If n is odd, add 5
    • Print n for each iteration. Why do you get the last value?
  3. Set a real value x=0. Loop from 1 to N inclusive by 1.
  • If the loop variable is less than M, add 11.0 to x.
  • If x > w and x < z, skip the iteration.
  • If x > 100., exit the loop.
  • Print the final value of x.
  • Experiment with different values for the variables. Start with N=50, M=25, w=9., z=13.
Example Solution

#include <iostream>

int main() {

    // 1)
    for (int i=0; i<=20; i+=2) {
	    std::cout << i << ",";
    }
    std::cout << "\n\n";

    // 2)
    int n=1;
    while (n<121) {
        if (n%2==0) {
            n+=3;
        } else {
            n+=5;
        }
	std::cout << n << ",";
    }
    std::cout << "\n\n";

    // 3)
    float x=0.;
    int N=50, M=25;
    float w=9., z=13.;

    for (int i=1; i<=N; ++i) {
        if (i<M) {
            x+=11.;
        }
        if (x>w && x<z) continue;
        if (x>100) break;
    }
    std::cout << x << "\n";
}

Previous
Next