Extra Loops

do-while loops

We've spent a lot of time with while-loops and for-loops. Both of these loops test whether to continue, and then go through the loop body, i.e. the test is done at the beginning of the loop. A "do-while" loop allows you to put the test at the end of the loop. This is convenient for certain tasks. For example, we looked at a program that reads expressions like:
1 + 5 + 3 + 48 + 32 =
and prints out the resulting sum. This can be done nicely with a do-while

#include <iostream>
using namespace std;

int main() {
  int next, sum = 0;
  char op;



  do {
    cin >> next;
    sum = sum + next;
    cin >> op;
  } while( op != '=' );

  return 0;
}

#include <iostream>
using namespace std;

int main() {
  int next, sum = 0;
  char op;

  // Must initialize with something other than '=' 
  // just to make sure we enter the loop the first time.
  op = 'X';
  while( op != '=' ) {
    cin >> next;
    sum = sum + next;
    cin >> op;
  }

  return 0;
}

In case you don't find that compelling, here's another example. Suppose we want to keep reading in ints from a list until we read a negative number.

#include <iostream>
using namespace std;

int main() {
  int n;

  do {
    cin >> n;
  } while( n >= 0 );


  return 0;
}
#include <iostream>
using namespace std;

int main() {
  int n;

  cin >> n;    // read n the first time...     
  while( n >= 0 ) {
    cin >> n;
  }

  return 0;
}

Using break

By default, a loop executes until its condition becomes false. The executing program checks this condition at the "top" of the loop.

This means that even if the boolean expression that makes up the condition becomes false before the program completes executing all the statements within the body of the loop, all the remaining statements in the loop's body must complete before the loop can once again check its condition. In other words, the while statement in and of itself cannot exit its loop somewhere in the middle of its body.

Ordinarily this behavior is not a problem. Usually the intention is to execute all the statements within the body as an indivisible unit. Sometimes, however, it is desirable to immediately exit the body instead. C ++ provides the break statements to to give programmers more flexibility designing the control logic of loops.

Suppose you want to write a program that works as follows:

To do so, you could write the following code:
    int sum = 0;
	int num = 0;
	ifstream fin("numbers");
	
	// we need to track whether we saw a negative number
	// goodsofar is true if there has been no negative number so far
	bool goodsofar = true;

	while ( (fin >> num) && goodsofar ) {
    if( num >= 0 )		 // Check whether num is negative or not.  
		  sum = sum + num;
    else
		  goodsofar = false;
	}

	cout << sum << endl;

In particular, we needed to create a variable goodsofar to track down whether the program has met a negative number.

With a break statement, we can write a simpler code. In C++, a break statement causes the program to immediately exit from the body of the loop. In our scenario, the program can simply exit the loop as soon as it meets a native number. Therefore, we can simplify the code as follows:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	int sum = 0;
	int num = 0;
	ifstream fin("numbers");
	
	while (fin >> num) {
		// Exit the loop if num is negative
		if( num < 0 ) break;

		sum = sum + num;
	}
	cout << sum << endl;

	return 0;
}
Note: in the case of nested loops, break only "breaks out of" the innermost of the loops in which it appears.

Using continue

When a program's execution meets a break statement inside a loop, it skips the rest of the body of the loop and exits the loop. The continue statement is similar to the break statement, except the continue statement does not necessarily exit the loop. The continue statement skips the rest of the body of the loop and immediately checks the loop's condition. If the loop's condition remains true, the loop's execution continues at the top of the loop.

Let's slightly change the above program's behavior as follows:

Using the continue-statement, we can write the following code:
// Add the numbers in a file while skipping a negative number
#include <iostream>
#include <fstream>
using namespace std;

int main() {
	int sum = 0;
	int num = 0;
	ifstream fin("numbers");
	
	while (fin >> num) {
		// Skip the loop if num is negative
		if( num < 0 ) continue;

		sum = sum + num;
	}
	cout << sum << endl;

	return 0;
}

Printing prime numbers

A prime number is an integer greater than one whose only factors (also called divisors) are one and itself. For example, 29 is a prime number (only 1 and 29 divide into it with no remainder), but 28 is not (2, 4, 7, and 14 are factors of 28). Prime numbers were once merely an intellectual curiosity of mathematicians, but now they play an important role in cryptography and computer security.

Let's write a program that displays all the prime numbers less than a value entered by the user. A typical running of the program looks as follows:

$ ./primes
Display primes up to what value? 90
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 
We can start with structuring the code as follows:
  
  // Receive the max value
	cout << "Display primes up to what value? ";
	cin >> max_val;

	// Test each number n from 2 to max_val-1
	for( int n=2; n<max_val; n++ ) {
		// For each number i from 2 to n-1,
		// check if i is a factor of n 
		for( ; ; ) {
			// If a factor is found, n is not prime. 
			// So, exit the loop
		}

		// If no factor is found, then n is a prime number.
		// So, print n 
	}
Let's fill in more code. To check if a is a factor of n, we can compute the remainder when n is divided by a. If the remainder is 0, then a is a factor of n.
  
  // Receive the max value
	cout << "Display primes up to what value? ";
	cin >> max_val;

	// Test each number n from 2 to max_val-1
	for( int n=2; n<max_val; n++ ) {
		// For each number i from 2 to n-1,
		// check if i is a factor of n 
		for( int i=2; i<n; i++ ) {
			// If a factor is found, n is not prime. 
			// So, exit the loop
			if( n % i == 0 ) 	// Recall % computes a remainder
				break;
		}

		// If no factor is found, then n is a prime number.
		// So, print n 
		if ( /* some code */  )
			cout << n << " ";
	}

	cout << endl;
How do we check if no factor has been found for n? We can create a boolean variable has_factor to record this status.
  
  // Receive the max value
	cout << "Display primes up to what value? ";
	cin >> max_val;

	// Test each number n from 2 to max_val-1
	for( int n=2; n<max_val; n++ ) {
		bool has_factor = false;
		
		// For each number i from 2 to n-1,
		// check if i is a factor of n 
		for( int i=2; i<n; i++ ) {
			// If a factor is found, n is not prime. 
			// So, exit the loop
			if( n % i == 0 ) { 	// Recall % computes a remainder
				has_factor = true;
				break;
			}
		}

		// If no factor is found, then n is a prime number.
		// So, print n 
		if ( !has_factor )
			cout << n << " ";
	}

	cout << endl;

The complete code is shown below:

#include <iostream>
using namespace std;

int main() {
	// Receive the max value
	int max_val;
	cout << "Display primes up to what value? ";
	cin >> max_val;

	// Test each number n from 2 to max_val-1
	for( int n=2; n<max_val; n++ ) {
		bool has_factor = false;
		
		// For each number i from 2 to n-1,
		// check if i is a factor of n 
		for( int i=2; i<n; i++ ) {
			// If a factor is found, n is not prime. 
			// So, exit the loop
			if( n % i == 0 ) { 	// Recall % computes a remainder
				has_factor = true;
				break;
			}
		}

		// If no factor is found, then n is a prime number.
		// So, print n 
		if( !has_factor )
			cout << n << " ";
	}

	cout << endl;
	return 0;
}

Exiting main() early

The "return 0;" at the end of your program exits your program. In fact, inside main you can stick a "return 0;" wherever you want and as often as you want, and it'll exit the program.

For example, maybe you want to write a program that reads an integer k from the user and writes out 1/k. If the user enters zero, of course, there's a problem. Now we'll just castigate the user and exit the program if he does that!

#include <iostream>
#include iomanip>
using namespace std;

int main() {
	// Get number from user
	cout << "Enter a non-zero integer: ";
	int k;
	cin >> k;

	// Deal with bad input
	if( k == 0 ) {
		cout << "You follow directions like a Firstie!" << endl;
		return 1;
	}

	// Write out decimal approximation of 1/k
	cout << "1/" << k << " is " << 1/double(k) << endl;

	return 0;
}
You may prefer to use "exit(1)" instead of "return 1", since when we eventually write code outside of the main() block "exit(1)" sill still exit the program, but "return 1" won't. The "exit" function is available from the "iostream" library, for example.

Problems

  1. Write a program that draws a triangular tree, and the user provides the tree's height. A typical run of the program looks like the following:

    $ ./tree
    Enter height of tree: 10
              *
             ***
            *****
           *******
          *********
         ***********
        *************
       ***************
      *****************
     *******************
    
    The source code is given here.