Chapter 6. Decision and Control Statements

Once a decision was made, I did not worry about it afterward.

Harry Truman

Calculations and expressions are only a small part of computer programming. Decision and control statements also are needed, to specify the order in which statements are to be executed.

So far you have constructed linear programs, which are programs that execute in a straight line, one statement after another. In this chapter you will see how to change the control flow of a program with branching statements and looping statements . Branching statements cause one section of code to be executed or not, depending on a conditional clause . Looping statements are used to repeat a section of code a number of times or until some condition occurs.

if Statement

The if statement allows you to put some decision-making into your programs. The general form of the if statement is:

if (condition)
    statement; 

If the expression is true (nonzero), the statement is executed. If the expression is false (zero), the statement is not executed. For example, suppose you are writing a billing program. At the end, if the customer owes nothing or if he has credit (owes a negative amount), you want to print a message. In C++ this is written:

if (total_owed <= 0) 
    std::cout << "You owe nothing.
";

The operator <= is a relational operator that represents less than or equal to. This statement reads, “If the total_owed is less than or equal to zero, print the message.” The complete list of relational operators is found in Table 6-1.

Table 6-1. Relational operators

Operator

Meaning

<=

Less than or equal to

<

Less than

>

Greater than

>=

Greater than or equal to

==

Equal

!=

Not equal

Multiple relational expressions may be grouped together with logical operators. For example, the statement:

if ((oper_char == 'Q') || (oper_char == 'q'))
    std::cout << "Quit
";

uses the logical OR operator ( ||) to cause the if statement to print “Quit” if oper_char is either a lowercase “q” or an uppercase “Q”. Table 6-2 lists the logical operators.

Table 6-2. Logical operators

Operator

Usage

Meaning

Logical OR (||)

(expr1) || (expr2)

True if expr1 or expr2 is true

Logical AND (&&)

(expr1) && (expr2)

True if expr1 and expr2 are true

Logical NOT (!)

!(expr)

Returns false if expr is true; returns true if expr is false

Multiple statements after the if may be grouped by putting them inside curly braces ({ }). For example:

if (total_owed <= 0) { 
    ++zero_count; 
    std::cout << "You owe nothing.
";
}

For readability, the statements enclosed in curly braces are usually indented. This allows the programmer to quickly tell which statements are to be conditionally executed. As you will see later, mistakes in indentation can result in programs that are misleading and hard to read.

else Statement

An alternative form of the if statement is:

if (condition)
    statement; 
else 
    statement;

If the condition is true, the first statement is executed. If it is false, the second statement is executed. In our accounting example, we wrote out a message only if nothing was owed. In real life, we probably want to tell the customer how much he owes if there is a balance due.

if (total_owed <= 0) 
    std::cout << "You owe nothing.
"; 
else 
    std::cout << "You owe " << total_owed << " dollars
";

Tip

Note to Pascal programmers: Unlike Pascal, C++ requires you to put a semicolon at the end of the statement before the else .

Now consider this program fragment:

if (count < 10)     // If #1 
    if ((count % 4) == 2)   // If #2
        std::cout << "Condition:White
"; 
  else   // (Indentation is wrong)
      std::cout << "Condition:Tan
";

There are two if statements and one else . To which if does the else belong? Pick one:

  1. It belongs to if #1.

  2. It belongs to if #2.

  3. You don’t have to worry about this situation if you never write code like this.

The correct answer is 3. According to the C++ syntax rules, the else goes with the nearest if, so 2 is syntactically correct. But writing code like this violates the KISS principle (Keep It Simple, Stupid). It is best to write your code as clearly and simply as possible. This code fragment should be written as follows:

if (count < 10) {       // If #1
    if ((count % 4) == 2)   // If #2 
        std::cout << "Condition:White
"; 
    else 
        std::cout << "Condition:Tan
"; 
}

From our original example, it was not clear which if statement had the else clause; however, adding an extra set of braces improves readability, understanding, and clarity.

How Not to Use std::strcmp

The function std::strcmp compares two C-style strings and returns zero if they are equal and nonzero if they are different. To check whether two C-style strings are equal, we use code like the following:

    // Check for equal
    if (std::strcmp(string1, string2) == 0) 
       std::cout << "Strings equal
"; 
    else 
       std::cout << "Strings not equal
";

Some programmers omit the comment and the == 0 clause, leading to the following, confusing code:

    if (std::strcmp(string1, string2)) 
        std::cout << "......";

At first glance, this program obviously compares two strings and executes the std::cout statement if they are equal. Unfortunately, the obvious is wrong. If the strings are equal, std::strcmp returns zero, and the std::cout is not executed. Because of this backwards behavior, you should be very careful in your use of strcmp and always comment its use.

(The problem with std::strcmp is another reason that C++ style strings are easier to use than the old C-style strings.)

Looping Statements

To get a computer to repeat its work, you need a loop statement. Looping statements have many uses, such as counting the number of words in a document or the number of accounts that have past due balances.

while Statement

The while statement is used when the program needs to perform repetitive tasks. The general form of a while statement is:

while (condition)
    statement;

The program repeatedly executes the statement inside the while until the condition becomes false (0). (If the condition is initially false, the statement will not be executed.)

For example, Example 6-1 computes all the Fibonacci numbers that are less than 100. The Fibonacci sequence is:

1 1 2 3 5 8 . . .

The terms are computed from the equations:

1
1
2 = 1 + 1
3 = 2 + 1
5 = 3 + 2

etc.

In general, the Fibonacci sequence is defined as:

fn = fn - 1 + fn - 2

This is a mathematical equation using math-style variable names (fn). Mathematicians use this very terse style of naming variables, but in programming, terse is dangerous, so we translate these names into something verbose for C++:

Mathematician

Programmer

fn

next_number

fn-1

current_number

fn-2

old_number

So in C++ code, the equation is expressed as:

    next_number = current_number + old_number;

We want to loop until our current term is 100 or larger. The following while loop will repeat our computation until we reach this limit.:

    while (current_number < 100)

In our while loop we compute the value of current_number. Next we need to advance one term.

This completes the body of the loop. The first two terms of the Fibonacci sequence are 1 and 1. We initialize our first two terms to these values.

Figure 6-1 shows what happens to the variables during the execution of the program.

Fibonacci execution
Figure 6-1. Fibonacci execution

At the beginning, current_number and old_number are 1. We print the value of the current term. Then the variable next_number is computed (value 2). Next we advance one term by putting current_number into old_number and putting next_number into current_number. This is repeated until we compute the last term and the while loop exits. Example 6-1 shows our algorithm written as C++ code.

Example 6-1. fib/fib.cpp
#include <iostream>

int   old_number;     // previous Fibonacci number
int   current_number; // current Fibonacci number 
int   next_number;    // next number in the series

int main(  )
{
    // start things out 
    old_number = 1;
    current_number = 1;

    std::cout << "1
"; // Print first number

    while (current_number < 100) {

        std::cout << current_number << '
';
        next_number = current_number + old_number;

        old_number = current_number;
        current_number = next_number;
    }
    return (0);
}

break Statement

We have used a while statement to compute Fibonacci numbers less than 100. The loop exits when the condition at the beginning becomes false. Loops also can be exited at any point through the use of a break statement.

Suppose you want to add a series of numbers and you don’t know how many numbers are to be added together. You want to read numbers and need some way of letting the program know it has reached the end of the list. Example 6-2 allows you to use the number zero (0) to signal the end of the list.

Note that the while statement begins with:

while (true) {

The program will loop forever because the while would exit only when the expression true is false. The only way to exit this loop is through a break statement.

We detect the end-of-list indicator (zero) with the statement following if statement, then use break to exit the loop.

if (item == 0) 
     break;
Example 6-2. total/total.cpp
#include <iostream>

int   total;  // Running total of all numbers so far
int   item;   // next item to add to the list 

int main(  )
{
    total = 0;
    while (true) {
        std::cout << "Enter # to add 
";
        std::cout << "  or 0 to stop:";
        std::cin >> item;

        if (item == 0)
            break;

        total += item;
        std::cout << "Total: " << total << '
';
    }
    std::cout << "Final total " << total << '
';
    return (0);
}

Note that this program makes use of an old programming trick called an indicator to end the input. In this example, our end-of-input indicator is the number 0.

continue Statement

The continue statement is similar to the brea k statement, except that instead of terminating the loop, it starts re-executing the body of the loop from the top. For example, let’s modify the previous program to total only numbers larger than 0. This means that when you see a negative number, you want to skip the rest of the loop. To do this you need an if to check for negative numbers and a continue to restart the loop. The result is Example 6-3.

Example 6-3. total2/total2.cpp
#include <iostream>

int   total;       // Running total of all numbers so far 
int   item;        // next item to add to the list
int   minus_items; // number of negative items 

int main(  )
{
    total = 0;
    minus_items = 0;
    while (true) {
        std::cout << "Enter # to add
";
        std::cout << "  or 0 to stop:";
        std::cin >> item;

        if (item == 0)
            break;

        if (item < 0) {
            ++minus_items;
            continue;
        }
        total += item;
        std::cout << "Total: " << total << '
';
    }

    std::cout << "Final total " << total << '
';
    std::cout << "with " << minus_items << " negative items omitted
";
    return (0);
}

The Assignment Anywhere Side Effect

C++ allows the use of assignment statements almost anyplace. For example, you can put an assignment statement inside another assignment statement:

// don't program like this
average = total_value / (number_of_entries = last - first);

This is the equivalent of saying:

// program like this
number_of_entries = last - first; 
average = total_value / number_of_entries;

The first version buries the assignment of number_of_entries inside the expression. Programs should be clear and simple and should not hide anything. The most important rule of programming is KEEP IT SIMPLE.

C++ also allows you to put assignment statements in the while conditional. For example:

// Do not program like this
while ((current_number = last_number + old_number) < 100) {
    do_something_with_numbers();
    std::cout << "Term " << current_number << std::endl;
}

Avoid this type of programming. Notice how much clearer the logic is in the following version:

// Program like this
while (true) {
    current_number = last_number + old_number;

    if (current_number >= 100)
         break;

    do_something_with_numbers();
    std::cout << "Term " << current_number << std::endl;
}

Question 6-1: For some strange reason, the program in Example 6-4 thinks that everyone owes a balance of 0 dollars. Why?

Example 6-4. balance/balance.cpp
#include <iostream>

int   balance_owed;     // amount owed 

int main(  )
{
    std::cout << "Enter number of dollars owed:";
    std::cin >> balance_owed;

    if (balance_owed = 0)
        std::cout << "You owe nothing.
";
    else
        std::cout << "You owe " << balance_owed << " dollars.
";

    return (0);
}

Sample output:

Enter number of dollars owed: 12 
You owe 0 dollars.

Programming Exercises

Exercise 6-1: A professor generates letter grades using Table 6-3.

Table 6-3. Grade values

% Correct

Grade

0-60

F

61-70

D

71-80

C

81-90

B

91-100

A

Write a program that accepts a numeric grade and displays the corresponding letter grade.

Exercise 6-2: Modify the previous program to print out a + or - after the letter grade based on the last digit of the score. The modifiers are listed in Table 6-4.

Table 6-4. Grade-modification values

Last digit

Modifier

1-3

-

4-7

<blank>

8-0

+

For example, 81=B-, 94=A, and 68=D+. Note that an F is only an F; there is no F+ or F-.

Tip

Programmers frequently have to modify code that someone else wrote. A good exercise is to take someone else’s Exercise 6-2 and modify it.

Exercise 6-3: Given an amount less than $1.00, compute the number of quarters (25¢), dimes (10¢), nickels (5¢), and pennies (1¢) needed. Use your own currency if you want to.

Exercise 6-4: A leap year is any year divisible by 4 unless it is divisible by 100, but not 400. Write a program to tell whether a year is a leap year.

Exercise 6-5: Write a program that, given the number of hours an employee worked and her hourly wage, computes her weekly pay. Count any hours over 40 as overtime at time-and-a-half.

Answers to Chapter Questions

Answer 6-1: This program illustrates one of the most common and most frustrating errors a beginning C++ programmer makes. The problem is that C++ allows assignment statements inside if conditionals. The statement:

if (balance_owed = 0)

uses a single equal sign instead of the double equal. C++ will assign balance_owed the value 0 and then test the result (which is zero). If the result were nonzero (true), the if clause would be executed. Since the result is zero (false), the else clause is executed and the program prints the wrong answer.

The statement

if (balance_owed = 0)

is equivalent to

balance_owed = 0; 
if (balanced_owed != 0)

The statement should be written:

if (balance_owed == 0)

I once taught a course in C programming. One day about a month after the course had ended, I saw one of my former students on the street. He greeted me and said, “Steve, I have to tell you the truth. During the class I thought you were going a bit overboard on this single equal versus double equal bug, until now. You see, I just wrote the first C program for my job, and guess what mistake I made.”

One trick many programmers use is to put the constant first in any == statement. For example:

if (0 == balanced_owed)

This way, if the programmer makes a mistake and puts in = instead of ==, the result is:

if (0 = balanced_owed)

which causes a compiler error. (You can’t assign balance_owed to 0.)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.59.192