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 variablel
: Lower boundu
: Upper bounds
: Stride, or increment. Usually we usei++
for a stride of 1.s
can be negative, in which casel
must be greater thanu
. For an increment of -1 usei--
.
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
- Loop from 0 to 20 by increments of 2. Make sure that 20 is included. Print the loop variable at each iteration.
- 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?
- 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";
}