2 + 3 * 5 is evaluated? Do I get 17 or 25? Well, your
math classes should've taught you that 17 is the answer, and indeed
that's true in C++ as well.
When you have two different operators in an expression and parenthisization does not tell you which operation is performed first, the relative precedence of operators is what determines which operation is performed first.
Since * has a higher precedence than +, the expression
2 + 3 * 5 is evaluated like
2 + (3 * 5). But what about when both operators
are the same, or both have the same precedence? What happens
with a * b * c?
When you have two identical operators in an expression (or two different operators with the same precedence) and parenthisization does not tell you which operation is performed first, the associtivity of the operator(s) is what determines which operation is performed first.
The associtivity of * and / (which both have the same
precedence) is left-to-right, so
a * b * c is evaluated as (a * b) * c.
This can matter in C++. (For example, what does
3 / 4 * 1.5 evaluate to?) However ...
Always use parentheses rather than relying on subtle precedence and associtivity rules!
This table lists the operators and their associtivites. They are grouped together on lines with operators of the same precedence, and the lines go from highest precedence at the top, to lowest at the bottom. You should know about precedence and associtivity, and you should be able to use tables like this to fix precedence and associtivity related bugs, but rely on parentheses when you're unsure.
Associativity matters: An expression like
cout << 3.0 << " percent" relies on
associtivity of the << operator to make sense.
Why? First of all, you must understand that evaluating an
expression of the form cout << x
produces an object (with type and value!), just as evaluating
expressions usually do,
and that object is in fact cout. Of course we
concentrate on the side effect that evaluating this
expression has, which is to send output to standard out.
However, the fact that the object produced by the evaluation is
actually cout itself is important. The second thing to know is
that the operator << is left associative,
i.e. is evaluated left-to-right. So,
cout << 3.0 << " percent"
is evaluated as
(cout << 3.0) << " percent".
This way, when the part in the parenthises is evaluated, 3.0 is
output to the screen as a side effect, and the object returned
is cout. This leaves us with cout << "percent"
left to evaluate, which has the desired side effect of printing
" percent" to the screen after 3.0.
Of course, cin >> expressions work the same way.
Associativity also makes expressions like a = b = 0
do what you want. Only in this case = is is right-to-left
associative, so we get a = (b = 0). The key here
is that an assignment expression evaluates to the value of the
left-hand-side
object after the assignment. So b gets assigned value
zero, the expression has value zero, and then that's what is
assigned to a.
int k;
cin >> k;
if (k is even)
{
cout << "even" << endl;
}
else
{
cout << "odd" << endl;
} |
Of course we've got to figure out some C++ that will do the
"k is even" for us. What's inside
the ()'s in an if statement needs to be an
expression that evaluates to type boolean - if the
expression evaluates to true the first block of
code (code surrounded by {}'s forms a block) is
exectuted, otherwise the block following the
else is executed. This is called the test
condition.
|
k to be even,
k % 2 must be zero. We can test this using the
== operator. A single "=" in C++ is used for
assigning values to variables, a double "=" (i.e. ==)
is used to test whether two values are equal. A "=="
expression evaluates to an object of type bool that is
true if the left and right-hand expressions are
equal, and false otherwise. Thus,
(k % 2) == 0 is the test condition we need.
int k;
cin >> k;
if ((k % 2) == 0)
{
cout << "even" << endl;
}
else
{
cout << "odd" << endl;
} |
[The Complete Program] |
"even" if k is even and
"odd" otherwise. Then, after the if-statment, we'll
do the printing. We might implement it like this:
if ((k % 2) == 0)
{
string s;
s = "even";
}
else
{
string s;
s = "odd";
}
cout << s << endl;
However, when we try to compile this the compiler
complains that s is "an undeclared
identifier", which is exactly what it would say if we'd
never defined s at all. Well, as far as the
compiler is concerned when it processes the
"cout << s << endl;" statement, we
haven't defined s. The problem is caused
by the scope of variables in C++.
In C++, a variable only exists from the point at which it is
declared to the } that closes off the
innermost block in which it was declared. So the s
that we define inside the else-block is invisible, is unknown,
does not exist outside of that else-block. In particular, this
is true for our cout-statement. The scope
of a variable is the portion of the code that "sees" the
variable, i.e. that knows it exists. The scope of a
variable ends with the innermost block in which it was defined.
To fix up this version of our even/odd programm, we simply need
to move the declaration of s outside of the
if/else-blocks so that its scope extends to cout
statement. This'll work:
string s;
if ((k % 2) == 0)
{
s = "even";
}
else
{
s = "odd";
}
cout << s << endl;
==" 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)As you can see from the operator precedence table, they have lower precedence than the arithetic operators, so things like
2*k > k + 5
do what we'd like them to do - they evaluate the arithetic
expressions on the left and right, then they apply the
">" operator to compare the two values. This means, for example,
that instead of writing ((k % 2) == 0) we could
write (k % 2 == 0) and get the same result.
So what happens when we compare objects of different type?
For example, what happens with 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. Thus, 5 == 5.2 is false,
since 5 is converted to 5.0 prior to the comparison, and we end
up actually doing 5.0 == 5.2.
if
is followed by a block (the then block) and the else is
followed by a block (the else block). You've already
seen one example of a block: The block following
main(). Anything you can write inside of the
main block, you can write inside of any block.
This means that our then blocks and else blocks can declare
variables, read input, make assignments to variables
... anything. So, suppose I wanted to write a program that
would compute areas of circles and triangles for the user, first
asking the user which kind of object he was interested in. My
program might look something like:
int main()
{
// Read type of object: circle or triangle
string s;
cout << "Do you have a circle or a triangle? ";
cin >> s;
if (s == "circle")
{
// Compute area of circle
}
else
{
// Compute area of triangle
}
return 0;
}
... where we'd have to fill in the then-block with code that gets
the radius of the circle and computes and outputs its area, and
we'd have to fill in the else-block with code that reads in the
base and height from the user and computes and outputs the
triangle's area.
| Code for circle area | Code for triangle area |
double r,Pi;
Pi = 3.14159265358979324;
cout << "Enter the radius of your circle: ";
cin >> r;
cout << "Area equals " << Pi*r*r << endl;
|
double b,h;
cout << "Enter base length: ";
cin >> b;
cout << "Enter height: ";
cin >> h;
cout << "Area equals " << 1/2.0*b*h << endl;
|
Each of these "miniprograms" can be placed in its appropriate block, and we get the whole program.
int from the user and we want to change it to its
absolute values and print it out.
We'd probably write something like this:
int k;
cin >> k;
if (k < 0)
{
k = -1*k;
}
else
{
// nothing to do!
}
cout << k << endl;
When there's nothing to do in the else-block, we can simply drop
it. (Sometimes your if-statement is written so that the then-block
is empty and the else-block isn't. You can't simply drop the
then-block, so first rewrite your if-statement with a new
condition so that the then-block contains the work.)
int k;
cin >> k;
if (k < 0)
{
k = -1*k;
}
cout << k << endl;
10:02AM.)
Here
are two different solutions to this problem:
Version 1 and
Version 2.