Control
Selection
Selection allows us to execute a statement only if a certain condition is true:
if (CONDITION) CONSEQUENT
CONSEQUENT is any statement and CONDITION is any expression. Note the required parenthesis around the condition. If the value produced by the condition is non-zero, the consequent is executed, otherwise control passes to the next statement in the program. Although the condition can be any expression, it's more common to use an expression that produces a value of type bool: true ( = 1) or false ( = 0). For example, to avoid computing the square root of a negative number we write:
if (0 <= x) y = sqrt(x);
Selection also allows us to specify an alternative statement to execute in case the condition is false:
if (CONDITION) CONSEQUENT else ALTERNATIVE
If the condition produces 0, the alternative is executed and the consequent is ignored. If the condition produces a non-zero value if consequent is executed and the alternative is ignored. For example:
if (0 <= x) y = sqrt(x); else y = sqrt(-x);
Input Validation
Until now, we have been assuming that user inputs will be valid. This is a dangerous assumption. We can use selection to validate the input. If the input is invalid, we can write an error message to cerr:
int main()
{
double num;
cout << "Enter a non-negative number: ";
cin >> num;
if (num < 0)
cerr << "Error: number must be non-negative\n";
else
cout << "sqrt(" << num << ") = " << sqrt(num) << '\n';
return 0;
}
Multi Way Selection
Selection only allows us to choose one of two statements. What if we want to choose one of many statements? C++ does provide the switch statement:
int main()
{
int dig;
string digit;
cout << "Enter a digit: ";
cin >> dig;
switch(dig)
{
case 0: digit = "zero"; break;
case 1: digit = "one"; break;
case 2: digit = "two"; break;
case 3: digit = "three"; break;
case 4: digit = "four"; break;
case 5: digit = "five"; break;
case 6: digit = "six"; break;
case 7: digit = "seven"; break;
case 8: digit = "eight"; break;
case 9: digit = "nine"; break;
default: cerr << "Error: invalid digit\n";
}
cout << "You entered: " << digit + '\n'; // + = append
return 0;
}
Switch is awkward, for example forgetting a break; statement causes the subsequent cases to be executed. Also, the key (dig) must be in an enumeration or integral type.
Note the use of the string type in this example. To make this work we need to include string.h:
#include <iostream>
#include <string>
using namespace std;
Nested Selections
Another technique is to nest selection statements:
if (5 < x)
cout << "x is bigger than 5\n";
else if (4 < x)
cout << "x is between 4 and 5\n";
else if (3 < x)
cout << "x is between 3 and 4\n";
else if (2 < x)
cout << "x is between 2 and 3\n";
else if (1 < x)
cout << "x is between 1 and 2\n";
else if (0 < x)
cout << "x is between 0 and 1\n";
else
cout << "x is non positive\n";
Be careful of the dreaded dangling else problem:
if (x < 5)
if (x < 4)
cout << "x is smaller than 4\n";
else
cout << "Is x less than 5?\n";
What happens if x = 4.5? Does the alternative go with the first condition or the second? Answer: the alternative is matched with the closest condition, so the statement prints:
"Is x less than 5?"
Boolean-Valued Expressions
Conditions are often Boolean-valued expressions, i.e., expressions that produce a value of type bool (true or false) when executed. Be careful when testing for equality. In C++ this is done using the == operator:
if (x == 0)
cout << "x is 0\n";
else
cout << "x isn't 0\n";
An innocent mistake is to use the assignment operator:
if (x = 0) // error, use ==
cout << "x is 0\n";
else
cout << "x isn't 0\n";
This always executes the alternative, because the assignment statement produces the value 0, which is interpreted as false.
Inequality is tested using the != operator:
if (x != 0)
cout << "x isn't 0\n";
else
cout << "x is 0\n";
Boolean combinations are formed using the || (logical or) and && (logical and) operators:
if (0 < x && x < 1)
cout << "x is between 0 and 1\n";
if (x < 0 || 1 < x)
cout << "x isn't between 0 and 1\n";
Of course short-circuit evaluation is used by these operators: the operands are evaluated from left to right until the answer is known. The remaining operands are ignored. For example, if x is 0, then the expression
x != 0 && 1/x < 1e-20
produces the value false without attempting to divide 1 by 0.
Blocks
What if we want to execute several statements if a condition is true? A block statement allows us to group several statements by surrounding them with curly braces:
{ STATEMENT ... STATEMENT }
A block is treated like a single statement. For example, assume we prompt the user for a, b, and c, the coefficients of a quadratic ax2 + bx + c. Next, we calculate b2 – 4ac, the discriminant:
double disc = b * b - 4 * a * c; // discriminant
If the discriminant is non-negative, we calculate and print the roots, otherwise we terminate the program with an error message:
if (0 <= disc)
{
double root1 = (-b + sqrt(disc))/(2 * a);
double root2 = (-b - sqrt(disc))/(2 * a);
cout << "root 1 = " << root1 << '\n';
cout << "root 2 = " << root2 << '\n';
return 0;
}
else
{
cerr << "Roots are complex\n";
return 1;
}
Note the placement of the curly braces. Also note that no terminating semicolon is required after a block statement.
Of course declarations, such as the declarations of root1 and root2, can be placed inside blocks. The scope of a such a declaration—i.e., the region of the program where the name can be used –extends from the declaration to the terminating curly brace. For example:
{
int z = x; // error, x undefined
int x = 10;
int y = x; // ok, y = 10
int u = u; // ok, but stupid, u = ?
}
int z = x; // error: x out of scope
A name can only be declared once within a block:
{
int x = 10;
int x = 10; // error, x defined twice
}
We can redefine x in an nested block. In this case the more recent declaration eclipses the older declaration. For example:
{
int x = 10;
cout << x << '\n'; // prints 10
{
cout << x << '\n'; // prints 10
int x = 20;
cout << x << '\n'; // prints 20
}
cout << x << '\n'; // prints 10
}
Example: Computing Progressive Tax
Income tax is computed on a progressive scale. There is no tax on the first $5000 of income. Tax is 10% for the next $15000 of income, 20% for the next $30000 of income, and 30% for the remaining income. Tax laws change, so let's define all these numbers as constants that can easily be changed. Our program prompts the user for an income, then uses a nested selection to compute the tax:
int main()
{
const double maxRate = .3; // 30%
const double medRate = .2; // 20%
const double minRate = .1; // 10%
const double maxMedIncome = 50000; // $50000
const double maxMinIncome = 20000; // $20000
const double maxLowIncome = 5000; // $5000
const double maxMinTax = // tax on $20000
minRate * (maxMinIncome - maxLowIncome);
const double maxMedTax = // tax on $50000
medRate * (maxMedIncome - maxMinIncome) + maxMinTax;
double income = 0, tax = 0;
cout << "Enter income: ";
cin >> income;
if (maxMedIncome < income)
tax = maxRate * (income - maxMedIncome) + maxMedTax;
else if (maxMinIncome < income)
tax = medRate * (income - maxMinIncome) + maxMinTax;
else if (maxLowIncome < income)
tax = minRate * (income - maxLowIncome);
else if (0 <= income)
tax = 0;
else
{
cerr << "Error: income must be non-negative\n";
return 1;
}
cout << "Tax on $" << income << " = $" << tax << '\n';
return 0;
}
Here's a sample output from the program:
Enter income: 45000
Tax on $45000 = $6500
Iteration
An interpreter is a program that:
1. prompts the user for a command
2. executes the command
3. displays the result
4. repeats, unless the command was the quit command
How do we get steps 1 through 3 to repeat an indefinite number of times?
We can repeat a statement until a condition becomes false (i.e., 0) by using an unbounded iterator. C++ has two:
while (CONDITION) STATEMENT
do STATEMENT while (CONDITION);
CONDITION is any expression, but typically it is a Boolean-valued expression. Note the required parenthesis surrounding the condition and the required semicolon following the do-statement. Of course STATEMENT can be any type of statement, including a block statement.
STATEMENT and CONDITION are executed until CONDITION produces a false or 0 value. These are called unbounded because the condition may never produce a false value, in which case the computer loops forever. (Try typing <Ctrl> c to stop the program.) If the condition is initially true, how will it ever become false? Presumably, executing the statement will eventually change some variables that the condition depends on.
The difference between do and while is that while executes its condition before its statement, but do executes its statement first, then its condition. In fact, we don't need do, because we can implement it using while:
{ STATEMENT; while (CONDITION) STATEMENT }
This only matters if the initial value produced by the condition is false. The do loop will execute STATEMENT at least once.
Let's design an interpreter that:
1. prompts user for a number
2. computes and displays the number's square root
3. asks user if the user wants to quit
4. repeats if the answer is no
The main feature of our interpreter is a while loop controlled by a Boolean-valued variable called more, which is initially true:
while(more)
{
// prompt for a number: x
// calculate and display sqrt(x)
// prompt user for a character: response
more = (response != 'q');
}
Here the full program:
int main()
{
bool more = true;
double x = 0;
char response;
while(more)
{
cout << "Enter a number: ";
cin >> x;
if (x < 0)
cout << "The number must be non negative\n";
else
{
cout << "sqrt(" << x << ") = " << sqrt(x) << '\n';
cout << "Press any key to continue or q to quit: ";
cin >> response;
more = (response != 'q') && (response != 'Q');
}
}
return 0;
}
Don't forget the include directives you'll need at the top of your file:
#include <iostream>
#include <cmath> // needed for sqrt
using namespace std;
Here's a sample output produced by the program:
Enter a number: 49
sqrt(49) = 7
Press any key to continue or q to quit: x
Enter a number: 100
sqrt(100) = 10
Press any key to continue or q to quit: s
Enter a number: 36
sqrt(36) = 6
Press any key to continue or q to quit: q
Input Streams
One problem with our interpreter is that it lies! If the user presses the space bar, return/enter key, or tab key in response to the "Press any key ... " prompt, nothing happens. This is because the extraction operator skips white space, so the line:
cin >> response;
blocks until a non-white space character is read. How can we correct this problem?
A stream is an example of an object. We will study objects in great detail, later. For now, it suffices to know that an object encapsulates variables and functions. We can access a variable, var, encapsulated by an object, obj, using the syntax:
obj.var
We can call a function, fun, encapsulated by obj using the syntax:
obj.fun(x, y, z)
The basic function encapsulated by an input stream extracts a single character (including white space):
char c = cin.get(); // place next character in c
Another version takes a variable as a parameter:
cin.get(c); // place next character in c
Of course passing a constant to get fails:
cin.get(6 * 7); // error, no place to put the character!
Most streams buffer their characters, so it's possible to put an extracted character back into the input stream:
cin.putback(c);
Or we can simply peek at the next character in the input stream:
c = cin.peek();
This is equivalent to:
char temp = cin.get();
cin.putback(temp);
Here's a new version of the interpreter's while loop that uses cin.get():
while(more)
{
cout << "Enter a number: ";
cin >> x;
if (x < 0)
cout << "The number must be non negative\n";
else
{
cout << "sqrt(" << x << ") = " << sqrt(x) << '\n';
cout << "Press any key to continue or q to quit: ";
response = cin.get();
more = (response != 'q') && (response != 'Q');
}
}
This is a spectacular disaster! After the user enters a number, the square root is displayed, the "press any key ... " prompt is displayed, but then the user isn't given an opportunity to respond. Instead, the user is immediately prompted for another number:
Enter a number: 49
sqrt(49) = 7
Press any key to continue or q to quit: Enter a number:
If the user attempts to quit by typing q, the program enters spews prompts on the screen without pausing for any more user input! What's going on?
It's too inefficient to move one character at a time from an input device into the computer's memory, so most computers transfer blocks of characters into a hidden buffer. This is called buffering. Usually, characters are transferred from the buffer to program variables when a newline character is added to the buffer (i.e., when the user presses the Enter/Return key), but this can be implementation-dependent. For example, executing the expression:
char next = cin.get();
blocks the program. The user may now type a string of characters on the keyboard:
abcdefghijklmnopqrstuvwxyz
Still nothing may happen. All of these characters have been transferred to the buffer associated with cin:

The first character is transferred into next and the program resumes execution only after a newline character enters the buffer:

In our example the input, "49", was translated into the number 49, then transferred to the variable, x, after the newline character enters the buffer:

Next, the "Press any key ... " prompt is displayed and cin.get() is executed. This transfers the newline character into the response variable. Since newline isn't 'q' or 'Q', the loop is re entered and the user is prompted for another number.
If the user types q to this prompt, then the extraction operator attempts to translate the character q into a number. Of course this fails, breaking cin. Once cin is broken, all future extractions turn into no-ops, which causes the run away behavior.
How can we fix the problem? Well, cin encapsulates a function that flushes the buffer. In C++ this is called synchronizing the buffer with the program's variables, so the function is called sync() instead of flush(). Here's our new while loop:
while(more)
{
cout << "Enter a number: ";
cin >> x;
if (x < 0)
cout << "The number must be non negative\n";
else
{
cout << "sqrt(" << x << ") = " << sqrt(x) << '\n';
cout << "Press any key to continue or q to quit: ";
cin.sync(); // flush \n from the buffer
response = cin.get();
more = (response != 'q') && (response != 'Q');
}
}
Of course a larger issue is what happens if the user inadvertently types a non number in response to the "Enter a number: " prompt? For example, what if the user types "nine" or "9" instead of 9? This will break cin and consequently, the program itself. Later we will see how to fix this problem.
The for Loop
Often, we want more control over how many times a loop must be executed. For these situations, C++ provides the for loop statement:
for(INIT; CONDITION; STEP) STATEMENT
INIT, CONDITION, and STEP are any expressions. They are all optional, so we can leave them out if we don't need them. After executing INIT, the for loop repeatedly executes CONDITION, STATEMENT, and STEP, until CONDITION produces a 0 value. It is equivalent to:
INIT
while(CONDITION)
{
STATEMENT;
STEP;
}
Typically, for loops are controlled by an integer loop control variable (LCV) that keeps track of how many times the loop is executed. The LCV can be used in the statement, too.
For example, the n-th triangle number is the number of bricks required to make a staircase n steps high:

Clearly, the n-th triangle number is 0 + 1 + 2 + 3 + ... + n. We can calculate this using a for loop:
int n = 0, tri = 0;
cout << "Enter height of the staircase: ";
cin >> n;
for(int i = 0; i <= n; i++) tri += i;
cout << "Number of bricks required = " << tri << '\n';
The LCV is i. Assume n = 5, we can trace the execution of the for loop to see how tri is computed:
i = 0 tri = 0
1 1
2 3
3 6
4 10
5 15
6
Example: Counting the Number of Ways to Choose
How many ways are there to choose a basket ball team from 10 people? How many 5-card poker hands are there? How many ways are there to choose m items from n items? The formula for computing this is:
fact(n)/(fact(m) * fact(n – m))
fact(k) represents the product of all integers from 1 to k = k * (k – 1) * ... * 1.
We can compute fact(n), fact(m), and fact(n – m) using three for loops:
for (int i = 1; i <= n; i++) fact1 *= i;
for(i = 1; i <= m; i++) fact2 *= i;
for(i = 1; i <= n - m; i++) fact3 *= i;
where fact1, fact2, and fact3 are integers initialized to 1:
long unsigned int fact1 = 1, fact2 = 1, fact3 = 1;
We choose long unsigned int as the type because factorials can become large fast. Notice that it isn't necessary to declare the LCV, i, in the second and third for loops. The final result is:
choices = fact1/(fact2 * fact3);
Notice that the parenthesis around the denominator are needed. Because / and * have the same precedence, these operations will be executed from left to right without the parenthesis, which would be equivalent to:
fact3 * fact1/fact2
The initial conditions are complicated. If n = m or if m = 0, then choices = 1. If n < m, then choices = 0. If m = 1 or m = n – 1, then choices = n. Here's the completed program:
int main()
{
int n = 0, m = 0;
long unsigned int fact1 = 1, fact2 = 1, fact3 = 1;
long unsigned choices = 0;
bool more = true;
char response;
while(more)
{
cout << "Enter number of items to choose from: ";
cin >> n;
cout << "Enter number of items to choose: ";
cin >> m;
if (m == 0 || m == n)
choices = 1;
else if (n < m)
choices = 0;
else if (m == 1 || m == (n - 1))
choices = n;
else
{
fact1 = fact2 = fact3 = 1;
for (int i = 1; i <= n; i++) fact1 *= i;
for(i = 1; i <= m; i++) fact2 *= i;
for(i = 1; i <= n - m; i++) fact3 *= i;
choices = fact1/(fact2 * fact3);
}
cout << "number of ways to choose = " << choices << '\n';
cout << "Press any key to continue or q to quit: ";
cin.sync();
response = cin.get();
more = (response != 'q') && (response != 'Q');
}
return 0;
}
Here's a sample output from the program. The last input caused the program to crash because the numbers got too large. We could attempt to fix the problems by using floating point numbers, instead of integers:
Enter number of items to choose from: 6
Enter number of items to choose: 3
number of ways to choose = 20
Press any key to continue or q to quit:
Enter number of items to choose from: 10
Enter number of items to choose: 5
number of ways to choose = 5040
Press any key to continue or q to quit:
Enter number of items to choose from: 52
Enter number of items to choose: 5