3.4.1. If-Statements

Time: 00:03:46 | Download: Large, Large (CC), Small | Streaming Streaming (CC) | Slides (PDF)

If-statements are among the most simple and the most easily understood control statements. Their simplicity notwithstanding, if-statements are powerful and essential in contemporary programs written in various programming languages. If-statements follow one of three basic formats:

Each format is explored in detail below. The conditional expression driving each if-statement in the following code fragments is abbreviated simply as "Test" or "Test n." This convention is just a shorthand notation representing a logical Boolean-valued expression, which may be simple or arbitrarily complex. For example: counter < 10 or counter > 0 && counter < MAX

Simple if-Statements

A simple if-statement executes a single statement, whether a block statement or not, depending on the test outcome. We generally base the tests on the values stored in one or more program variables. The results of the tests change as the values stored in the variables change during program execution, which means that the statements inside the if-statement execute sometimes but not other times. The following flow chart illustrates the behavior of a simple if-statement.

A logic diagram or flowchart. Execution enters the diagram at a test; if the test is true, a statement executes. Execution leaves the diagram after the statement ends or if the test is false.
A logic diagram of a simple if-statement. If the test evaluates to true, then the statement is executed. The else part of an if-statement is optional, so if the test evaluates to false, then the if-statement does nothing. Braces are optional in the case of a single statement in the body of the if-statement.

The code fragments below demonstrate the basic pattern of a simple if-statement. The definition of a statement given previously is applied recursively here. That is Statement 1 is a single statement, but so is if (Test) Statement 1 (the complete statement ends with a single semicolon). The second and third examples each form single if-statements; the braces form a block that the if treats like a single statement (note the absence of a semicolon following the closing brace). Finally, in the second example, the braces surrounding "Statement 1" are optional - some programmers always use braces, while others do not.

if (Test)
	Statement 1;



if (Test)
{
	Statement 1;
}

if (Test)
{
	Statement 1;
	Statement 2;
}
(a)(b)(c)
if-Statement variations.
  1. An if-statement containing a single statement
  2. An if-statement with optional braces
  3. An if-statement based on a compound or block statement; the braces are required
int	x = 10;

if (x > 0)
	cout << "it is greater than\n";
int	x = 10;

if (x < 10)
	cout << "it is less than\n";
it is greater than No output
Simple if-statement behavior. If the test evaluates to true, the output statement runs; otherwise, the if-statement does nothing.

if-else Statements

Whereas a simple if-statement chooses to execute a statement or not, an if-else statement chooses to execute one of two statements, either or both of which may be a block statement, as illustrated in the figure below.

A logic diagram. Execution enters the diagram at a test. If the test is true, statement 1 executes; if the test is false, statement 2 executes.
A logic diagram of an if-else statement. An if-else statement has two possible paths of execution. If the test is true, the program runs statement 1; otherwise, it runs statement 2. The keyword else separates the statements. As before, braces are optional when a single statement appears in either the if or the else branch.

"Statement 1" always follows the keyword if, while "Statement 2" always follows the keyword else, as illustrated by the patterns below. A well-formed if-statement requires the if keyword, the parentheses, and a valid test, but the else and the associated statement are optional.

if (Test)
	Statement 1;
else
	Statement 2;
	
	
	
	
	
	
	
	
	
	
	
	
if (Test)
{
	Statement 1;
		.
		.
		.
	Statement n;
}
else
{
	Statement 1;
		.
		.
		.
	Statement m;
}
(a)(b)
if-else statement variations.
  1. When a single statement appears in either the true or false branch, braces are optional
  2. Braces are required whenever more than one statement appears in a branch

If-Else Ladder

An if-else ladder does not introduce additional keywords or symbols. The statement forms each new ladder rung with an if-else statement nested inside the else part of the previous if-else statement. If-else ladders also represent an exception to the earlier rule of thumb to restrict nesting to no more than four or five levels; the nesting must be deep enough to accommodate every possible branch required by the problem logic.

The logic diagram of an if-else ladder consists of a sequence of tests. Each test has one entrance and two exit paths. If the test is true, the program executes the corresponding statement, but if the test is false, then the execution is passed to the next test.
Logic diagram of an if-else ladder. An if-else ladder potentially has many execution paths. The program processes the ladder from top to bottom and executes the first statement whose test is true. If there is an else (without a test) and none of the tests are true, then the last statement executes; if there isn't an else (without a test) and none of the tests are true, then the ladder does nothing - no statements in the ladder run.

The following code fragments demonstrate the basic if-else ladder patterns:

if (Test 1)
	Statement 1;
else if (Test 2)
	Statement 2;
else if (Test 3)
	Statement 3;
else if (Test n)
	Statement n;
	
	
	
	
	
	
	
	
	
if (Test 1)
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement j;
}
else if (Test 2)
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement k;
}
else if (Test 3)
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement l;
}
else if (Test n)
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement m;
}
else
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement n;
}
(a)
if (Test 1)
	Statement 1;
else if (Test 2)
	Statement 2;
else if (Test 3)
	Statement 3;
else if (Test n)
	Statement n;
else
	Statement m;




(b)(c)
if-else ladder variations.
  1. if-else ladder without an ending else; the program doesn't run any ladder statements if all of the tests evaluate to false
  2. if-else ladder with an else at the end; statement m executes if all of the tests evaluate to false
  3. An if-else ladder with block statements
if (Test 1)
{
	Statement 1;
	Statement 2;
	   . . . .
	Statement j;
}
else
	if (Test 2)
	{
		Statement 1;
		Statement 2;
		   . . . .
		Statement k;
	}
	else
		if (Test 3)
		{
			Statement 1;
			Statement 2;
	   		. . . .
			Statement l;
		}
		else
			if (Test n)
			{
				Statement 1;
				Statement 2;
	   			. . . .
				Statement m;
			}
			else
			{
				Statement 1;
				Statement 2;
	   			. . . .
				Statement n;
			}
Diagonal if-else ladder. Some programmers wish to emphasize the nesting that is taking place within an if-else ladder by writing the ladder diagonally. The way you write an if-else ladder is largely a matter of personal taste and style, but in my experience, most programmers use the straight rather than the diagonal format.
if-else statementif-else ladder
int	x = 5;
double	y = 3.14;

if (x > y && x != 10)
	cout << "true\n";
else
	cout << "false\n";







int	score = 87;

if (score >= 95)
	cout << "Grade: A\n";
else if (score >= 90 && score < 95)
	cout << "Grade: A-\n";
else if (score >= 85 && score < 90)
	cout << "Grade: B+\n";
else if (score >= 80 && score < 85)
	cout << "Grade: B\n";
else if (score >= 75 && score < 80)
	cout << "Grade: B-\n";
else (score < 75)
	cout << "Grade: E\n";
true Grade: B+
Complex if-else behavior. Unlike a simple if-statement, an if-else statement will always execute one branch: the first branch if the test evaluates to a "true" value and the second (else) branch if the test evaluates to "false." An if-else ladder repeatedly extends an if-statement by nesting a new if-else in the else part of the previous statement. Both examples illustrate more complex conditional tests and the output from the code fragments.

The Dangling Else Problem

It's essential to remember that we use indentation in a C++ program to make the code's logic more apparent to people. Indentation is not part of the language's syntax and does not affect the meaning of the code in any way. (Alternatively, indentation is relevant in a Python program where indentation rather than braces indicate nesting.) The "dangling else problem" results from an over-dependence on indentation. Look very closely at the indentation in the first code fragment, which suggests what the programmer intended the code to do. The accompanying logic diagram also illustrates the programmer's intention.

Intended
if (test 1)
	if (test 2)
		statement 1;
else
	statement 2;
The diagram illustrates the programmer's intended logic, as suggested by the code's indentation. Execution enters the diagram at test 1. If the test evaluates to false, statement 2 runs, and execution leaves the diagram. Otherwise, execution passes to test 2. If test 2 is false, the execution leaves the diagram without the nested if-statements doing anything. If test 2 is true, then statement 1 runs.
The dangling-else problem. The indentation used in the if-else statement implies that the programmer intends to execute statement 1 only if both Test 1 and Test 2 are true, and if test 1 is false, then execute statement 2. That is, the programmer wants the else clause to match the first if and have the meaning illustrated by the logic diagram. However, the else always matches the "nearest" if. When the if-statement runs, it will not behave as the programmer wants. The dangling-else problem is an example of a logical error.
Actual
if (test 1)
	if (test 2)
		statement 1;
	else
		statement 2;
The diagram illustrates the actual behavior of the nested if-statements. If test 1 is false, nothing happens. If test 1 is true, then the inner if-statement runs. If test 2 is true, statement 1 runs, else statement 2 runs.
Understanding the dangling-else code. Rewriting the code is the easiest way to understand the actual behavior of the dangling-else problem. Shift the indentation of the second if-statement so that each else lines up with the matching "if." Now, it's easier to see the code's true behavior, as illustrated in the logic diagram.
Corrected Statement
if (test 1)
{
	if (test 2)
		statement 1;
}
else
	statement 2;
The diagram indicates the corrected behavior of the nested if-statements. If test 1 is false, statement 2 runs. If test 1 is true, then test 2 is evaluated, and if it's true, statement 1 runs.
The correcting the dangling-elsp problem. Braces are required to achieve the meaning implied by the indentation in the original dangling-else code fragment. Is the dangling-else problem a valid argument in favor of always using braces? Perhaps, but would we be better off if the code included every possible brace but placed some incorrectly? Obviously not. The key is understanding what we are doing and examining and testing our code to ensure it behaves correctly. Remember the rule that the else clause always binds to the nearest if clause.

If you are interested in a more technical description of the problem and its history, you can read more in the Wikipedia article Dangling else.