(Last Mod: 27 November 2010 21:38:36 )
The C programming language provides several selection structures to aid in structured programming. The if(), if()/else statements and the conditional operator perform a "1 of 2" path selection based on a logical test expression. The switch() statement performs a "1 of N" path selection based on the evaluation of an integer expression.
In each of the descriptions below, an example code fragment containing the
structure being discussed will be presented. To illustrate how this structure
appears in the context of the code around it, the structure is preceded by a
code block called prior_code
and followed by a code block
called next_code
. These blocks are not part of the
structure. To emphasize this, the corresponding flowchart will have a dashed
line surrounding just that portion of the chart which is part of the structure
being discussed.
One thing to note is that, in each case, the dashed block represents a block of code that conforms to the single-entry/single-exit paradigm.
if()
StatementThe syntax of the if() statement is as follows:
prior_code;
if (test)
if_code;
next_code;
After the prior_code
block as finished, the
test
expression, which can be any expression that yields a value,
is evaluated. If that value is identically equal to zero it is considered
False and the if_code
block is skipped. If it evaluates to
any value other than zero, the if_code
block is executed.
In either case, the next_code
block is then executed.
The if_code
block consists of exactly one statement.
But that one statement can be a null statement (which would be the case if a
semicolon were accidentally placed after the closing parentheses of the test
expression, a single statement, or a compound statement. An example of the
latter case, which is extremely common, is shown below:
prior_code;
if (test)
{
/* if_code block */
statement_1;
statement_2;
...
statement_N;
}
next_code;
A very common mistake that people make is to write code as follows:
prior_code;
if (test)
statement_1;
statement_2;
next_code;
Visually, this looks like both
statement_1
and statement_2
are
controlled by the if()
statement. They are not. The
if()
statement controls only the next statement - which in this
case is just statement_1
. Regardless of the outcome
of test
, statement_2
will always
execute. This code is perfectly legal and will compile without warnings - the
compiler does not consider indentation when compiling code.
if()/else
StatementThe syntax of the if()/else statement is as follows:
prior_code;
if (test)
if_code;
else
else_code;
next_code;
After the prior_code
block as finished, the
test
expression, which can be any expression that yields a value,
is evaluated. If that value is identically equal to zero it is considered
False and the if_code
block is skipped but the
else_code
block is executed. If it evaluates to any value other
than zero, the if_code
block is executed but the
else_code
block is skipped. In short, this construct ensured that
exactly one of the two blocks will be executed. In either case, the
next_code
block is then executed.
The if_code
and else_code
blocks
consist of exactly one statement. But that one statement can be a null
statement (which would be the case if a semicolon were accidentally placed
after the closing parentheses of the test expression and/or the else
keyword, a single statement, or a compound statement. An example of the latter
case, which is extremely common, is shown below:
prior_code;
if (test)
{
/* if_code block */
statement_1;
statement_2;
...
statement_N;
}
else
{
/* else_code block */
statement_1;
statement_2;
...
statement_N;
}
next_code;
In many respects, the else
portion can be thought of as a completely separate statement which happens to
have the constraint that is must immediately follow an if()
statement and it's block only executes if the controlling if()
statement's block did not.
switch()
StatementThe syntax of the switch()
statement is as follows:
prior_code;
switch(test)
{
case constant1: statement 1;
statement_2;
break;
case constant2: statement_3;
case constantN: statement_4;
break;
default : statement_5;
statement_6;
}
next_code;
After the prior_code
block as finished, the
test
expression, which can be any expression that yields an integer
value, is evaluated. That value is then compared to the integer constant
associated with the first case
label in the code block
controlled by the switch()
statement. If it doesn't match,
it compares it to the next case
label. This continues
until either a match is found or the entire list of case
labels have been examined.
If a match is found, program control is transferred to the statement
immediately following the matching case
label. Execution
then continues until either the end of the code block is reached or a
break
statement is encountered. A break
statement forces execution to jump out of the block and proceed directly to
the next_code
block.
If a match is not found, then program control is transferred to the
statement following the optional default
label, if their
is one. If there isn't a default
label, the entire block
is skipped and control immediately passes to the next_code
block.
The constants associated with each case
label must be
unique, integer constants. They must be unique in that no other case
label in the same switch statement can have the same value. They must be
integers - which character constants are. They must be constants in that the
compiler - at compile time - must be able to evaluate any expression that is
there.
The case
labels can appear in any order, but the
default
label, if it exists, must appear last.
Notice in the above example that if the case associated with
constant2 is selected, then both statement3
and
statement4
will be executed. The fact that
statement4
is associated with the constantN
label is irrelevant. Read again what the description says: "Execution then
continues until either the end of the code block is reached or a
break
statement is encountered." Is says nothing about anything
happening if or when another case
label is encountered.
?:
Conditional OperatorThe conditional operator is a special form of an if/else structure that can appear in an expression.
The syntax for this operator is as follows:
test? T_expr : F_expr
If the test
expression, which can be any
expression that yields an value, is True (anything other than zero), then the
result of the entire expression is whatever the result of the T_expr
expression is. The F_expr
expression is never evaluated.
In contrast, if the test
expression evaluates as False
(exactly zero) then the T_expr
expression is never
evaluated and the result of the enture expression is whatever the result of
the F_expr
expression is.
Example: Print a plus or minus sign depending on whether a value is positive or negative:
putc( (x < 0)? '-' : '+', stdout);
If (x < 0)
True, the this statement essentially
becomes:
putc( '-', stdout);
Otherwise it essentially becomes:
putc( '+', stdout);