Using Control Structures:
Using Relational Operators:
== equal to x == y != not equal to x != y < less than x < y <= less than or equal to x <= y > greater than x > y >= greater than or equal to x >= y ***BE CAREFUL! 'a' < 'A' evaluates to false!***Under the ASCII Collating Sequence: numbers < ucase letters < lcase letters
Declarations: string str1 = "Hello"; string str2 = "Hi"; string str3 = "Ann"; string str4 = "Bill"; str1 < str2 //true: second character 'e' less than 'i' str4 < str3 //false: first character 'B' greater than 'A' str3 >= "An" //true: characters are equal, but str3 is longer than "An"
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.468This result is due to rounding errors. The variable fTotal is stored as 2.4679999, which is not 2.468!
if (x > 5.01) && (x < 5.03) cout << "Equal";
Using Logical (Boolean) Operators:
!true //evaluates to false !(5 >= 8) //evaluates to true: 5 >= 8 (false), !(false) is true
( numStudents >= 30 && classAverage >= 70 ) //there are at least 30 students and the classAverage is at least 70 ( numStudents >= 30 && !(classAverage < 70) ) //evaluates to same as above
To clarify the differences between using the logical (boolean) operators AND &&, OR ||, and bitwise operators AND &, OR |:Using bool Data Type and Logical (Boolean) Expressions:
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 somethingIf 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 somethingAgain, 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.
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.Mnemonic: "Math Relates Logically"
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
Using One-Way (if) Selection:
if (expression) statement1; statement2;
if (grade >= 90) cout << "Student has an A";
Using Two-Way (if...else) Selection:
if (expression) statement1; else statement2;
Using Compound (Block) Statement:
{ statement1; statement2; . . . statementn; }
if (age > 18) { cout << "Eligible to vote." << endl; cout << "No longer a minor." << endl; } else { cout << "Not eligible to vote." << endl; cout << "Still a minor." << endl; }
Using Nested if and if...else Statements:
{ if (condition1) statement1; else if (condition2) statement2; . . . else if (condition-n) statement-n; else statement-z; }
Example 1: { if (x < 0) y = -1; else if (x == 0) y = 0; else //(x > 0) y = 1; }
Example 2: { if (x < 0) y = -1; if (x == 0) y = 0; if (x > 0) y = 1; }
Using if Statement to Prevent Input Failure:
Using if Statement to Prevent Input Failure:
test_expression ? true_expression : false_expression
cout << (x > y ? "x is greater than y" : "x is less than or equal to y");//Equivalent to
if (x > y) cout << "x is greater than y"; else cout << "x is less than or equal to y");
Using switch Structures:
Note: series of case labels and optional default case Example 1: switch(x) { case x1: statements1; break; case x2: statements2; break; case x3: statements3; break; default: statements4; break; } Example 2: switch (integralTestExpression) { case value1: // taken if integralTestExpression == value1 statements...; break; // necessary to exit switch case value2: case value3: // taken if integralTestExpression == value2 or == value3 statements...; break; default: // taken if integralTestExpression matches no other cases statements...; break; }