Bruce Eckel's Thinking in C++, 2nd Ed Contents | Prev | Next

Controlling execution

This section covers the execution control statements in C++. You must be familiar with these statements before you can read and write C or C++ code.

C++ uses all C’s execution control statements. These include if-else, while, do-while, for, and a selection statement called switch. C++ also allows the infamous goto, which will be avoided in this book.

True and false

All conditional statements use the truth or falsehood of a conditional expression to determine the execution path. An example of a conditional expression is A == B . This uses the conditional operator == to see if the variable A is equivalent to the variable B . The expression produces a boolean true or false (these are keywords only in C++; in C an expression is “true” if it evaluates to a nonzero value). Other conditional operators are >, <, >=, etc. Conditional statements are covered more fully later in this chapter.

if-else

The if-else statement can exist in two forms: with or without the else. The two forms are:

if(expression)

statement

or

if(expression)

statement

else

statement

The “expression” evaluates to true or false. The “statement” means either a simple statement terminated by a semicolon or compound statement, which is a group of simple statements enclosed in braces. Any time the word “statement” is used, it always implies that the statement is simple or compound. Note this statement can also be another if, so they can be strung together.

//: C03:Ifthen.cpp
// Demonstration of if and if-else conditionals
#include <iostream>
using namespace std;

int main() {
  int i;
  cout << "type a number and 'Enter'" << endl;
  cin >> i;
  if(i > 5)
    cout << "It's greater than 5" << endl;
  else
    if(i < 5)
      cout << "It's less than 5 " << endl;
    else
      cout << "It's equal to 5 " << endl;

  cout << "type a number and 'Enter'" << endl;
  cin >> i;
  if(i < 10)
    if(i > 5)  // "if" is just another statement
      cout << "5 < i < 10" << endl;
    else
      cout << "i <= 5" << endl;
  else // Matches "if(i < 10)"
    cout << "i >= 10" << endl;
} ///:~

It is conventional to indent the body of a control flow statement so the reader may easily determine where it begins and ends [20].

while

while, do-while and for control looping. A statement repeats until the controlling expression evaluates to false. The form of a while loop is

while(expression)

statement

The expression is evaluated once at the beginning of the loop, and again before each further iteration of the statement.

This example stays in the body of the while loop until you type the secret number or press control-C.

//: C03:Guess.cpp
// Guess a number (demonstrates "while")
#include <iostream>
using namespace std;

int main() {
  int secret = 15;
  int guess = 0;
  // "!=" is the "not-equal" conditional:
  while(guess != secret) { // Compound statement
    cout << "guess the number: ";
    cin >> guess;
  }
  cout << "You guessed it!" << endl;
} ///:~

The while’s conditional expression is not restricted to a simple test as in the above example; it can be as complicated as you like as long as it produces a true or false result. You will even see code where the loop has no body, just a bare semicolon:

while(/* Do a lot here */)
;

In these cases the programmer has written the conditional expression not only to perform the test but also to do the work.

do-while

The form of do-while is

do

statement

while(expression);

The do-while is different from the while because the statement always executes at least once, even if the expression evaluates to false the first time. In a regular while, if the conditional is false the first time the statement never executes.

If a do-while is used in Guess.cpp, the variable guess does not need an initial dummy value, since it is initialized by the cin statement before it is tested:

//: C03:Guess2.cpp
// The guess program using do-while
#include <iostream>
using namespace std;

int main() {
  int secret = 15;
  int guess; // No initialization needed here
  do {
    cout << "guess the number: ";
    cin >> guess; // Initialization happens
  }   while(guess != secret);
  cout << "You got it!" << endl;
} ///:~

For some reason, most programmers tend to avoid do-while and just work with while.

for

A for loop performs initialization before the first iteration. Then it performs conditional testing and, at the end of each iteration, some form of “stepping.” The form of the for loop is:

for(initialization; conditional; step)

statement

Any of the expressions initialization, conditional or step may be empty. The initialization code executes once at the very beginning. The conditional is tested before each iteration (if it evaluates to false at the beginning, the statement never executes). At the end of each loop, the step executes.

for loops are usually used for “counting” tasks:

//: C03:Charlist.cpp
// Display all the ASCII characters
// Demonstrates "for"
#include <iostream>
using namespace std;

int main() {
  for(int i = 0; i < 128; i = i + 1)
    if (i != 26)  // ANSI Terminal Clear screen
      cout << " value: " << i <<
      " character: " << 
      char(i) << endl; // Type conversion
} ///:~

You may notice that the variable i is defined at the point where it is used, instead of at the beginning of the block denoted by the open curly brace ‘ {’. This is in contrast to traditional procedural languages (including C), which require that all variables be defined at the beginning of the block. This will be discussed later in this chapter.

The break and continue Keywords

Inside the body of any of the looping constructs while, do-while or for, you can control the flow of the loop using break and continue. break quits the loop without executing the rest of the statements in the loop. continue stops the execution of the current iteration and goes back to the beginning of the loop to begin a new iteration.

As an example of the use of break and continue, this program is a very simple menu system:

//: C03:Menu.cpp
// Simple menu program demonstrating
// the use of "break" and "continue"
#include <iostream>
using namespace std;

int main() {
  char c; // To hold response
  while(true) {
    cout << "MAIN MENU:" << endl;
    cout << "l: left, r: right, q: quit -> ";
    cin >> c;
    if(c == 'q')
      break; // Out of "while(1)"
    if(c == 'l') {
      cout << "LEFT MENU:" << endl;
      cout << "select a or b: ";
      cin >> c;
      if(c == 'a') {
        cout << "you chose 'a'" << endl;
        continue; // Back to main menu
      }
      if(c == 'b') {
        cout << "you chose 'b'" << endl;
        continue; // Back to main menu
      }
      else {
        cout << "you didn't choose a or b!"
             << endl;
        continue; // Back to main menu
      }
    }
    if(c == 'r') {
      cout << "RIGHT MENU:" << endl;
      cout << "select c or d: ";
      cin >> c;
      if(c == 'c') {
        cout << "you chose 'c'" << endl;
        continue; // Back to main menu
      }
      if(c == 'd') {
        cout << "you chose 'd'" << endl;
        continue; // Back to main menu
      }
      else {
        cout << "you didn't choose c or d!" 
             << endl;
        continue; // Back to main menu
      }
    }
    cout << "you must type l or r or q!" << endl;
  }
  cout << "quitting menu..." << endl;
} ///:~

If the user selects ‘q’ in the main menu, the break keyword is used to quit, otherwise the program just continues to execute indefinitely. After each of the sub-menu selections, the continue keyword is used to pop back up to the beginning of the while loop.

The while(true) statement is the equivalent of saying “do this loop forever.” The break statement allows you to break out of this infinite while loop when the user types a ‘q.’

switch

A switch statement selects from among pieces of code based on the value of an integral expression. Its form is:

switch(selector) {

case integral-value1 : statement; break;

case integral-value2 : statement; break;

case integral-value3 : statement; break;

case integral-value4 : statement; break;

case integral-value5 : statement; break;

(...)

default: statement;

}

Selector is an expression that produces an integral value. The switch compares the result of selector to each integral-value. If it finds a match, the corresponding statement (simple or compound) executes. If no match occurs, the default statement executes.

You will notice in the above definition that each case ends with a break, which causes execution to jump to the end of the switch body (the closing brace that completes the switch). This is the conventional way to build a switch statement, but the break is optional. If it is missing, your case “drops through” to the one after it. That is, the code for the following case statements execute until a break is encountered. Although you don’t usually want this kind of behavior, it can be useful to an experienced programmer.

The switch statement is a very clean way to implement multi-way selection (i.e., selecting from among a number of different execution paths), but it requires a selector that evaluates to an integral value at compile-time. If you want to use, for example, a string object as a selector, it won’t work in a switch statement. For a string selector, you must instead use a series of if statements and compare the string inside the conditional.

The menu example shown previously provides a particularly nice example of a switch:

//: C03:Menu2.cpp
// A menu using a switch statement
#include <iostream>
using namespace std;

int main() {
  bool quit = false;  // Flag for quitting
  while(quit == false) {
    cout << "Select a, b, c or q to quit: ";
    char response;
    cin >> response;
    switch(response) {
      case 'a' : cout << "you chose 'a'" << endl;
                 break;
      case 'b' : cout << "you chose 'b'" << endl;
                 break;
      case 'c' : cout << "you chose 'c'" << endl;
                 break;
      case 'q' : cout << "quitting menu" << endl;
                 quit = true;
                 break;
      default  : cout << "Please use a,b,c or q!"
                 << endl;
    }
  }
} ///:~

The quit flag is a bool, short for “Boolean,” which is a type you’ll only find in C++. It can only have the keyword values true or false. Selecting ‘q’ sets the quit flag to true. The next time the selector is evaluated, quit == false returns false so the body of the while does not execute.

Recursion

Recursion is an interesting and sometimes useful programming technique whereby you call the function that you’re in. Of course, if this is all you do you’ll keep calling the function you’re in until you run out of memory, so there must be some way to “bottom out” the recursive call. In the following example, this “bottoming out” is accomplished by simply saying that the recursion will only go until the cat exceeds ‘Z’: [21]

//: C03:CatsInHats.cpp
// Simple demonstration of recursion
#include <iostream>
using namespace std;

void removeHat(char cat) {
  for(char c = 'A'; c < cat; c++)
    cout << "  ";
  if(cat <= 'Z') {
    cout << "cat " << cat << endl;
    removeHat(cat + 1); // Recursive call
  } else
    cout << "VOOM!!!" << endl;
}

int main() {
  removeHat('A');
} ///:~

In removeHat( ), you can see that as long as cat is less than ‘Z’, removeHat( ) will be called from within removeHat( ), thus effecting the recursion. Each time removeHat( ) is called, its argument is one greater than the current cat so the argument keeps increasing.

Recursion is often used when evaluating some sort of arbitrarily complex problem, since you aren’t restricted to a particular “size” for the solution – the function can just keep recursing until it’s reached the end of the problem.


[20] Note that all conventions seem to end after the agreement that some sort of indentation take place. The feud between styles of code formatting is unending. See appendix A for the description of this book’s coding style.

[21] Thanks to Kris C. Matson for suggesting this exercise topic.

Contents | Prev | Next


Contact: webmaster@codeguru.com
CodeGuru - the website for developers.
[an error occurred while processing this directive]