==" is an example of a relational operator.
Relational operators make comparisons of their left and right-hand
arguments, and return bool values accordingly. They are:
== (equal), != (not equal), < (less than), > (greater than), <= (less than or equal to), >= (greater than or equal to)
2*k > k + 5
will evaluated as (2*k) > (k+5).
As another example, instead of writing ((k % 2) == 0) we could
write (k % 2 == 0) and get the same result.
string s = "hello";
string t = "banana";
if( s > t )
cout << "bigger" << endl;
else
cout << "smaller" << endl;
The above code will output "bigger", since "hello" will appear later than
"banana" in the dictionary.
k == x, where k is an int, and x is a double?
The answer is that the same automatic type conversions are applied as in arithmetic expressions. So, k is implicitly converted to a double, and this double value is compared to x.
&& (and), the ||
operator (or), and the ! (not) operator.
&&
|
At first glance, && looks like something
mysterious and new. It's not. It's an operator just like +, *,
and >>, all of which we've used a lot already.
It takes two objects of type
So, something like |
||
|
The || operator is much like &&, it
takes two objects of type bool and evaluates to an
object of type bool. The result is
true if either or both are true, and
false otherwise.
|
!
|
The ! operator is a unary operator.
Instead of operating on left and right-had values, it operates
on a single value - the value following it on the right. It
evaluates to the not of the value following, so if the value
following is true, the ! expression is
false.
|
Suppose you wanted to write the following expression:
(x == 3) || (x > y)
However, you wrote the code as follow by mistake:
(x = 3) || (x > y)
Interestingly, the second expression always evaluates true!
One single letter makes huge difference!
Let's see what's going on. The expression expr1 || expr2
follows short circuit evaluation rules, which means the following:
expr1 is evaluated first.
expr1 is true, just return true without evaluating
expr2.
Explanation: (expr1 || expr2) = (true or
expr2) is always true, whether expr2 is true or
not. So, expr2 is never even evaluated.
expr1 is false, evaluate expr2 and
return the final evaluation result.
Now consider our example:
(x = 3) || (x > y)
(x=3), which is an assignment expression with type
int and value 3, which is always converted boolean true.
(x > y) is never executed as explained
above.
asin
function from the cmath library to compute our value.
Now, the arcsine is only defined for values between negative 1 and
1, so if the user enters a value outside of this range we should
print an error message.
We want to be able to say in our test condition that x must be
less than or equal to 1 AND greater than or equal to -1.
In C++ the operator && is "and". So our
program fragment becomes:
if (x <= 1.0 && x >= -1.0)
{
cout << "arcsine of " << x << " = " << asin(x) << endl;
}
else
{
cout << "Error! Value outside of [-1,1]!" << endl;
}
-1.0 <= x <= 1.0 for testing
whether x is between -1.0 and 1.0.
Explanation: Since the two operators are the same, applying the
left-to-right associativity for the operator <=, the
above expression is evaluated as (-1.0 <= x) <= 1.0
(true <= 1.0). Since true will be
converted to 1.0, the overall expression is true.
(false <= 1.0). Since false will be
converte to 0.0, the overall expression is true.
-1.0 <= x <= 1.0 is always true!
But, of course, the problem is the test condition// Read char char c; cout << "Enter a letter: "; cin >> c; // Decide: Letter or not a letter? if (c is a letter) { cout << "Letter" << endl; } else { cout << "Not a Letter" << endl; }
c is a letter. Letters
come in two flavors, uppercase and lowercase. So a refinement of
our program would be:
From the ASCII table we would see that uppercase letters range from// Read char char c; cout << "Enter a letter: "; cin >> c; // Decide: Letter or not a letter? if (c is an uppercase letter || c is a lowercase letter) { cout << "Letter" << endl; } else { cout << "Not a Letter" << endl; }
'A' (65) to
'Z' (90). So c is an uppercase
letter boils down to (c >= 65 && c <= 90).
Similarly, because lowercase letters range from 'a' (97) up to
'z' (122), we know that c is a
lowercase letter boils down to (c >= 97 && c <= 122).
| Not recommended | Recommended -- better readability |
|
|
&&'s were evaluated before the ||. Is
that necessary? (Think about how you would decide this!) Even if
it isn't, adding the ()'s makes the meaning clear to everyone.
In fact, we can avoid having to even look at an ASCII table by replacing the
actual ASCII constants 65, 90, 97, and 122 with the corresponding
char constants for the letters 'A', 'Z',
'a', and 'z'. This also makes it much more clear how
the code works, and we recommend you to write your code this way.
Check out this complete solution.
else ifx of type
double that I know is between 0 and 1, and suppose I
want to print out for the user
x is in [0,1/3],
x is in [1/3,2/3], or
x is in [2/3,1]
x. Our first shot would probably be the
code on the left below. However, our "cout" statements are
if-blocks and else-blocks consisting of a single statement, so Shortcut #1 tells
us we can drop the {}'s surrounding those statments, which would give us the
code on the right below:
| First shot | Dropping {} |
|
|
if" statement is a single statement,
so Shortcut #1 tells us that we can drop the {}'s surrounding the
scond "if" statement, which would give us the code on the left
below.
However, the C++ compiler is not sensitive to to formatting, so it
doesn't distinguish between "if-newline-else" and "if-space-else", so we
could rewrite things to look like the code on the right below.
| Dropping {} further | Reformatting the code |
|
|
else if" as if it were a new programming
construct (which in some languages, it is), but you see it is just the
same code with the same meaning as our original ... it just looks a little
prettier, saves keystrokes, and takes up a little less screen real estate.
There's nothing new here! All we did was to take advantage of Shortcut #1
and to use some nice formatting. It sure looks prettier though. Once
again, this is just a shortcut to save keystrokes and screen space, and
to make your code easier to read - but you will see this shortcut often.
else if" formatting is particularly nice when you have
disjoint cases to distinguish. For example:
d of type string that contained a day of the
week name (e.g. Thursday), and
int k
that you wanted to set to the number of the day d (e.g. 5 for
Thursday).
else if". It makes a huge difference in terms of
how easy the code is to understand!
$ ./a.out Enter a letter: k Letter $ ./a.out Enter a letter: ! Not a letterCheck out the solution.
|
|
if( y != 0 && x != 0 )or
if( !( y ==0 || x == 0 ) )