5.3.1. The if Statement

Image

An if statement conditionally executes another statement based on whether a specified condition is true. There are two forms of the if: one with an else branch and one without. The syntactic form of the simple if is

if (condition)
     statement

An if else statement has the form

if (condition)
     statement
else
     statement2

In both versions, condition must be enclosed in parentheses. condition can be an expression or an initialized variable declaration (§ 5.2, p. 174). The expression or variable must have a type that is convertible (§ 4.11, p. 159) to bool. As usual, either or both statement and statement2 can be a block.

If condition is true, then statement is executed. After statement completes, execution continues with the statement following the if.

If condition is false, statement is skipped. In a simple if, execution continues with the statement following the if. In an if else, statement2 is executed.

Using an if else Statement

To illustrate an if statement, we’ll calculate a letter grade from a numeric grade. We’ll assume that the numeric grades range from zero to 100 inclusive. A grade of 100 gets an “A++,” grades below 60 get an “F,” and the others range in clumps of ten: grades from 60 to 69 inclusive get a “D,” 70 to 79 a “C,” and so on. We’ll use a vector to hold the possible letter grades:

const vector<string> scores = {"F", "D", "C", "B", "A", "A++"};

To solve this problem, we can use an if else statement to execute different actions for failing and passing grades:

// if grade is less than 60 it's an F, otherwise compute a subscript
string lettergrade;
if (grade < 60)
    lettergrade = scores[0];
else
    lettergrade = scores[(grade - 50)/10];

Depending on the value of grade, we execute the statement after the if or the one after the else. In the else, we compute a subscript from a grade by reducing the grade to account for the larger range of failing grades. Then we use integer division (§ 4.2, p. 141), which truncates the remainder, to calculate the appropriate scores index.

Nested if Statements

To make our program more interesting, we’ll add a plus or minus to passing grades. We’ll give a plus to grades ending in 8 or 9, and a minus to those ending in 0, 1, or 2:

if (grade % 10 > 7)
    lettergrade += '+';         // grades ending in 8 or 9 get a +
else if (grade % 10 < 3)
    lettergrade += '-';         // those ending in 0, 1, or 2 get a -

Here we use the modulus operator (§ 4.2, p. 141) to get the remainder and decide based on the remainder whether to add plus or minus.

We next will incorporate the code that adds a plus or minus to the code that fetches the letter grade from scores:

// if failing grade, no need to check for a plus or minus
if (grade < 60)
    lettergrade = scores[0];
else {
    lettergrade = scores[(grade - 50)/10]; // fetch the letter grade
    if (grade != 100)  // add plus or minus only if not already an A++
        if (grade % 10 > 7)
            lettergrade += '+';  // grades ending in 8 or 9 get a +
        else if (grade % 10 < 3)
            lettergrade += '-';  // grades ending in 0, 1, or 2 get a -
}

Note that we use a block to enclose the two statements that follow the first else. If the grade is 60 or more, we have two actions that we need to do: Fetch the letter grade from scores, and conditionally set the plus or minus.

Watch Your Braces

It is a common mistake to forget the curly braces when multiple statements must be executed as a block. In the following example, contrary to the indentation, the code to add a plus or minus happens unconditionally:

if (grade < 60)
    lettergrade = scores[0];
else  // WRONG: missing curly
    lettergrade = scores[(grade - 50)/10];
    // despite appearances, without the curly brace, this code is always executed
    // failing grades will incorrectly get a - or a +
    if (grade != 100)
        if (grade % 10 > 7)
            lettergrade += '+';  // grades ending in 8 or 9 get a +
        else if (grade % 10 < 3)
            lettergrade += '-';  // grades ending in 0, 1, or 2 get a -

Uncovering this error may be very difficult because the program looks correct.

To avoid such problems, some coding styles recommend always using braces after an if or an else (and also around the bodies of while and for statements).

Doing so avoids any possible confusion. It also means that the braces are already in place if later modifications of the code require adding statements.


Image Best Practices

Many editors and development environments have tools to automatically indent source code to match its structure. It is a good idea to use such tools if they are available.


Dangling else

When we nest an if inside another if, it is possible that there will be more if branches than else branches. Indeed, our grading program has four ifs and two elses. The question arises: How do we know to which if a given else belongs?

This problem, usually referred to as a dangling else, is common to many programming languages that have both if and if else statements. Different languages solve this problem in different ways. In C++ the ambiguity is resolved by specifying that each else is matched with the closest preceding unmatched if.

Programmers sometimes get into trouble when they write code that contains more if than else branches. To illustrate the problem, we’ll rewrite the innermost if else that adds a plus or minus using a different set of conditions:

// WRONG: execution does NOT match indentation; the else goes with the inner if
if (grade % 10 >= 3)
    if (grade % 10 > 7)
        lettergrade += '+';  // grades ending in 8 or 9 get a +
else
    lettergrade += '-'; // grades ending in 3, 4, 5, 6, or 7 get a minus!

The indentation in our code indicates that we intend the else to go with the outer if—we intend for the else branch to be executed when the grade ends in a digit less than 3. However, despite our intentions, and contrary to the indentation, the else branch is part of the inner if. This code adds a '-' to grades ending in 3 to 7 inclusive! Properly indented to match the actual execution, what we wrote is:

// indentation matches the execution path, not the programmer's intent
if (grade % 10 >= 3)
    if (grade % 10 > 7)
        lettergrade += '+';  // grades ending in 8 or 9 get a +
    else
        lettergrade += '-';  // grades ending in 3, 4, 5, 6, or 7 get a minus!

Controlling the Execution Path with Braces

We can make the else part of the outer if by enclosing the inner if in a block:

// add a plus for grades that end in 8 or 9 and a minus for those ending in 0, 1, or 2
if (grade % 10 >= 3) {
    if (grade % 10 > 7)
        lettergrade += '+';  // grades ending in 8 or 9 get a +
} else                  // curlies force the else to go with the outer if
    lettergrade += '-'; // grades ending in 0, 1, or 2 will get a minus

Statements do not span block boundaries, so the inner if ends at the close curly before the else. The else cannot be part of the inner if. Now, the nearest unmatched if is the outer if, which is what we intended all along.


Exercises Section 5.3.1

Exercise 5.5: Using an ifelse statement, write your own version of the program to generate the letter grade from a numeric grade.

Exercise 5.6: Rewrite your grading program to use the conditional operator (§ 4.7, p. 151) in place of the ifelse statement.

Exercise 5.7: Correct the errors in each of the following code fragments:

(a) if (ival1 != ival2)
    ival1 = ival2
else ival1 = ival2 = 0;

(b) if (ival < minval)
    minval = ival;
    occurs = 1;

(c) if (int ival = get_value())
    cout << "ival = " << ival << endl;
if (!ival)
    cout << "ival = 0 ";

(d) if (ival = 0)
    ival = get_value();

Exercise 5.8: What is a “dangling else”? How are else clauses resolved in C++?


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

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