Control Structures - Selection

Using Control Structures:


Relational Operators

Using Relational Operators:

Relational Operator Examples: ***Under the ASCII Collating Sequence: numbers < ucase letters < lcase letters
ASCII Chart

Comparing string Types: string Comparison Examples:
***Caution!***
Sometimes, programs are required to compare numbers and/or variable values. For example:
int x = 5; // integers have no precision issues   
if (x==5)   
    cout << "x equals 5" << endl;   
else  
    cout << "x does not equal 5" << endl;  

Program prints: x equals 5.
However, when using floating point numbers, unexpected results may occur, if the two numbers have very close values. For example:
float myFloat1 = 1.345f;   
float myFloat2 = 1.123f;   
float fTotal = myFloat1 + myFloat2; // should be 2.468   

if (fTotal == 2.468)   
    cout << "fTotal is 2.468";   
else  
    cout << "fTotal is not 2.468";  

Prints: fTotal is not 2.468
This result is due to rounding errors. The variable fTotal is stored as 2.4679999, which is not 2.468!

For this reason, comparison operators >, >=, <, and <= may produce incorrect results when comparing floating point numbers. Solution: Code to allow for some tolerance.
if (x > 5.01) && (x < 5.03) cout << "Equal";

Logical (Boolean) Operators

Using Logical (Boolean) Operators:

Logical (Boolean) Operator Examples:

Logical (Boolean) Expressions

To clarify the differences between using the logical (boolean) operators AND &&, OR ||, and bitwise operators AND &, OR |:

First of all, let me preface any comments by saying when using && or &, and || or |, ultimately the results are the SAME. When using && or & operators, both operands must be true, otherwise, false. When using || or | operators, both operands must be false, otherwise, true. The difference lies in the evaluation PROCESS.

Short-circuit evaluation: evaluation of a logical expression stops as soon as the value of the expression is known. When the && operator is used to compare a logical expression, the compiler will stop the evaluation upon the first false condition, unlike the & operator which will continue to evaluate the ensuing expression(s) being compared. The same holds true for the operators || and |, when evaluating true conditions.

With respect to logical vs. bitwise operators, there is a difference between using the logical "and" (&&), rather than the bitwise "and" (&). And, yes, there is a very important difference--and, no "one size fits all" solution:

When the logical (&&) operator is used to compare a logical expression, the compiler will stop the evaluation upon the first false condition, unlike the & operator which will continue to evaluate the ensuing expression(s) being compared.
if(++myVal % 2 == 0 && ++count < limit)
   // Do something
If the left hand operand is evaluated to be false (++myVal % 2 == 0), the compiler will stop and not evaluate the right-hand operand (++count < limit). More importantly, if myVal is not an even number, count will NOT increment.

This may be fine, IF count doesn’t need to increment every time. Though, if it does, use the bitwise "and" (&) operator to evaluate both expressions. As the following example:
if(++myVal % 2 == 0 & ++count < limit)
   // Do something
Again, fundamentally, the logical result is the same (i.e., a truth table) for both & and &&: "Do something" only will be executed if BOTH expressions are true. The benefit is that the bitwise "and" (&) operator will allow count to increment.

On the other hand, you may not want the right hand expression to be evaluated (that is, use && not &). Example:
If(count > 0 && total/count > 5)
Here, it's easy to see that one would NOT want a compile or run-time error if the value of count were 0!

Lastly, the same "truth table" logic holds true for logical "or" (||) vs. the bitwise "or" (|). That is, the || operator is like && in that the right hand operand is NOT evaluated if the left hand operand is TRUE. You would need to use | if you wanted BOTH expressions to be evaluated.
Using bool Data Type and Logical (Boolean) Expressions:

Operator Precedence and Associativity

Two operator characteristics determine how operands group with operators: precedence and associativity. Precedence is the priority for grouping different types of operators with their operands. Associativity is the left-to-right or right-to-left order for grouping operands to operators that have the same precedence. An operator's precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher-precedence operators are evaluated first. The grouping of operands can be forced by using parentheses.

Also, operators follow a strict precedence, which defines the evaluation order of expressions containing these operators. Operators associate with either the expression on their left or the expression on their right; this is called "associativity." The following table shows the precedence and associativity of C++ operators (from highest to lowest precedence). Operators in the same segment of the table have equal precedence and are evaluated left to right in an expression unless explicitly forced by parentheses.
Operator Precedence and Associativity 1
And...
Operator Precedence and Associativity 2
Mnemonic: "Math Relates Logically" Order of Precedence Examples (for complete listing, see links above):



One-Way (if) Selection

Using One-Way (if) Selection:


Two-Way (if...else) Selection

Using Two-Way (if...else) Selection:


Compound (Block) Statement

Using Compound (Block) Statement:

Compound Statement Example:

Nested if and if...else Statements

Using Nested if and if...else Statements:


Preventing Input Failure Using if Statement

Using if Statement to Prevent Input Failure:


Conditional Operator (?:)

Using if Statement to Prevent Input Failure:


switch Structures

Using switch Structures: