Expressions and Interactivity

See also

Text: Chapter 3

Once we have some data, specifically numerical data, to work with, we need to know what operations we can perform on them.

Precedence

You should already know about operator precedence. That is the set of rules the language follows when evaluating an expression. In general, we should have learned that multiplication and division always happen before addition and subtraction.

Parentheses

You should also know that you can force things to be evaluated the way you want is you use parentheses around subexpressions. The system works from the inner-most set of parentheses outward, evaluating subexpressions, and eliminating the parentheses as it works out the final value.

Consider this expression:

(x + y * z - (x - (y / z + 2) * z) + 5)

Phew! How will this be processed (and what kind of person invents such an expression?)

Here is how it will go:

(x + y * z - (x - (y / z + 2) * z) + 5)
(x + y * z - (x - (r1+ 2) * z) + 5)
(x + y * z - (x - r2 * z) + 5)
(x + y * z - (x - r3) + 5)
(x + y * z - r4 + 5)
(x + r5 - r4 + 5)
(r6 - r4 + 5)
(r7 + 5)
r8

The system hunted down the innermost set of parentheses and began evaluating that subexpression. It used normal operator precedence in doing this. When is completed that evaluation, it removed the expressions, and repeated the process looking for more parentheses to work on. It scans the complete expression each time from left to right looking for something to “reduce”. When all the parentheses are gone and all operators have been applied we are done.

That final answer is what is used as the result of the evaluation.

Data Types

Remember that C++ is a “strongly typed” language. That means it is serious about protecting data and not letting you mess with their data types. If you set up an integer variable, it will remain an integer variable for the life of the program.

So, how is C++ going to deal with something like this:

int X = 5;
float PI = 3.1415926;
int Z;

Z = X * PI + 2.5;

Here, we have two initialized variables. The names are recorded, along with the data type specified on each declaation. The first two are given an appropriate initial value.

The last declaration sets up an uninitialized variable.

Warning

That variable should be assumed to hold a junk value until you specifically place some useful value in it! Failing to remember this leads to errors in your code.

The last line is called an assignment statement. The expression on the right side of the equal sign is evaluated and then the resulting value is stored in the named variable on the left side of the equal sign. Simple. But what ends up stored in Z?

To figure this out, we need to use the precedence rules, and learn a simple fact about this kind of math:

If two numbers are combined using a math operator, he resulting value data
type will be:

    * integer if both numbers are integrs.

    * float if either number (or both) is a float.

So, how is this example evaluated?

  1. X (int) is multiplied by PI (float) producing a float value.

  2. That float value is added to 2.5 (float) producing another float.

  3. That float final value is stuffed into an int container. The system chops off the fractional part converting it into an integer and the statement is complete.

The conversion from float to integer is a bit more complex than it seems. Remember how things are encoded in the machine. The conversion has to work hard to figure out the precise new pile of binary bits to store in the final container.

C++ Operators

Here is a list of the standard operators available in C++. Many of these are available in Python, but a few Python operators are not available in C++.

Basic Arithmetic Operators

Operator

Operation

+

addition

-

subtraction

*

multiplication

/

division

%

modulo

The modulo operator gives the integer remainder after division.

13 % 4 ->  1

Increment/Decrement Operators

In programming, you often see statements like this:

x = x + 1;

These are so common, C++ provides a shortcut:

Operator

Operation

x++

post increment

x–

post decrement

++x

pre increment

–x

pre decrement

Understanding what is going on here is a bit tough. Normally, when you access a variable, you pull out the value stored there and use it in the expression it lives in. In the case of these operators, we still pull out the value stored in the container, but what happens depend on whether the operator is a pre or post one.

If it is a post operator, we use the current value stored in the container, then add one to that value and put it back in the named container. That increments the stored value.

If it is a pre operator, we pull out the value in the container, add one to it and use that new value in the expression, then we store that new value back in the named container.

As if that were not bad enough, this is perfectly legal:

x = 5;
y = ++x--;

What ends up in x, or y after these statements are processed?

Compound Operators

In the same spirit, there are simplifications for common statements like this:

x = x * 5;

Here are the new operators we can use:

Operator

Operation

x += 5

x = x + 5

x -= 5

x = x - 5

x *= 5

x = x * 5

x \= 5

x = x \ 5

Logical Operators

We need to ask questions, and those questions often ask us to compare two values. Here are the operators we can use:

Operator

Operation

==

exactly equal to

!=

not equal to

>

greater than

<

less than

>=

greater or equal

<=

less or equal

Logical Conjunction Operators

We can ask compound logical questions using the logical conjunction operators. There are the logical and, and logical or operators. We can also use logical negation (not):

operator

operation

&&

logical and

||

logical or

!

logical not

Short Circuit Evaluation

When using these conjunction operators, it is important to remember that once the value of the expression is known, evaluation stops. For instance, if we form this expression:

(x != 0) && (y / x)

It is not safe to perform the division in the second part of this expression if x has a value of zero. But the first part of this expression checks that. If the value stored in x is not zero, the first part evaluates to true. The second part needs to be evaluated to determine the final value of the expression.

If the value stored in x is zero, the value of the first part is false and it does not matter what the second part evaluates to, the result is false, so the processing will stop, and we will not divide by zero, which would cause problems. (what?)

Other Operators

There are a few other operators available, but they are not commonly used, especially by beginners. We will leave them to a later course.

Interaction

We do need to figure out how to input things from the user while the program is running. C++ provides this capability using features provided by the iostream package:

# include <iostream>

int X;
float Y;

cin >> X;
cin >> Y;

The system will pause when it processes this statement, and wait for the user to type something in on the keyboard. Each character will be processed until a character is encountered that is not legal for the data type of the variable we are using to capture the input value.

Normally, you should output a prompt`, telling the user to enter something. Otherwise they may stare at the screen wondering what is going on! They usually will enter something followed by typing a ``Return (or Enter) key.

If, instead, they enter a space, that will work, and the system will press on. The second line will be processed, and this time, the program expects a floating point number.

Note

For floating point numbers, it is possible to enter digits, periods (decimal point), signs, and even “scientific` notation (something like 1.023e-3)

The user will see what they entered since the console echoes what they type. It is possible for them to correct a mistake when typing by pressing the backspace key (or delete on a Mac).

Validating Input

Unfortunately, you cannot trust those “users”. They will try to break your program, just for fun.

The proper way to handle user input is not to trust them, ever! They may not do what you ask and your program should do something sane if they enter the wrong thing.

Instead, you make sure your program can handle whatever they do, and respond appropriately. If you ask them to enter an number and they type “no”, you should detect that, and remind them to enter a number. How you do this is something we will explore later. For now, we will do an evil thing, we will “trust” the user while we learn how to write C++ code! (That user will be yu, or me, when we are testing your code!)