Home Previous Next

CSC100 :: Lecture Note :: Week 04
Assignments | Code | Handouts | Resources | Email Thurman {Twitter::@compufoo Facebook::CSzero}
{GDT::Bits:: Time  |  Weather  |  Populations  |  Special Dates}

Overview

Assignment(s):

Code: arithmetic.cpp | years.cpp | years2.cpp | years3.cpp | Expressions0.cpp | Expressions1.cpp | if.cpp | if2.cpp

### Precedence and Associativity of Operators

Whenever you have an EXPR that contains multiple operators, then you must be aware of operator precedence and associativity.

Precedence and associativity are used to "bind" operators with operands.

Every C/C++ book that I have reviewed contains a precedence and associativity chart. Here is a chart that displays the precedence and associativity of some of the operators we learn first.

Unary + and - have higher precedence than the binary forms.
Operators Associativity
()   +   -   (type)   sizeof right to left
*   /   % left to right
+   - left to right
= right to left

Precedence determines the order in which operands are bound to operators. Operators on the same line have the same precedence; rows are in order of decreasing precedence.

Examples:

• The sizeof operator is high precedence, whereas the assignment operator = has low precedence.
• The multiple operator * is a medium precedence operator that has slightly higher precedence that the addition operator +.

If an EXPR contains two operators of equal precedence, then associativity is used to bind operators and operands.

An example using the EXPR:    a + b - c

The + and - operators have equal precedence; therefore, associativity
is used.  They associate left-to-right and we end up with with the
binding  (a + b) - c

Precedence and associativity can be altered by using parenthesis.

Example expression:  a * b / c

* and / have equal precedence and they associate left-to-right;
therefore, we get the following binding:  (a * b) / c

If we want the operand  b  to be attached to the operand  c,
then we would parenthesis and code the EXPR:  a * (b / c).

Use parenthesis if you are ever in doubt about the precedence and associativity rules. [Note: it is possible to overuse ()'s.]

GDT::Resource::C++:: Precedence chart that includes all operators.

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### Relational Operators

Relational operators are used to compare the value of two expressions (EXPRs).

  ==    != expr1 == expr2 equals expr1 != expr2 not equals expr1 > expr2 greater than expr1 < expr2 less than expr1 >= expr2 greater than or equal to expr1 <= expr2 less than or equal to

The operators that are made up of two characters cannot have any whitespace between. For example: = = would be treated as two separate assignment operators and would result in a compile-time error. == is used to test two operands for equality.

It is easy to sometimes use the equality operator in lieu of the assignment operator and vice versa. You must remember the following.

==   is the relational equality operator; it compares two operands
for equality and evaluates to either 0 (false) or 1 (true)

=    is the assignment operator; it copies the value of the operand
on the right-hand side to the operand on the left-hand side; the
EXPR evaluates to the value that was copied (i.e. assigned)

Examples.

int thisCourse = 100;   /* 100 assigned to thisCourse */
int nextCourse = 205;   /* 205 assigned to nextCourse */

thisCourse == nextCourse   /* evaluates to 0 (false) */
thisCourse != nextCourse   /* evaluates to 1 (true) */
thisCourse > nextCourse    /* evaluates to 0 */
thisCourse < nextCourse    /* evaluates to 1 */
thisCourse >= nextCourse   /* evaluates to 0 */
thisCourse <= nextCourse   /* evaluates to 1 */

GDT::C++::Code:: RelationalOps.cpp

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### The if Statement and else Clause

The if is a selection control statement. It is a keyword of the language. It has the following syntax.

if (EXPR)
statement';
statement'';

If  EXPR  evaluates to true (i.e. not zero), then  statement'  is
executed followed by statement''; otherwise,  statement'  is skipped
and the flow control of the program jumps to  statement''.

if (netWorth > 1000000)
cout << "you are rich (at least money wise)";
netWorth = netWorth * 2;   //let us double our net worth

Typically, there is no semicolon after the if. If there is, then the body of the if is simply a NULL (empty) statement. In many cases, this is a defect with your program (i.e. it is done by accident, not design).

if (netWorth < 0)
;  //do nothing...

If more than one statement needs to be executed when an if EXPR is true, then a compound statement. should be used. A compound statement is a collection of zero or more statements enclosed in braces {}.

Compound statements are terminated by the closing brace } -- not a semicolon.

if (EXPR) {
statement';
statement'';
}                //note that there is no semicolon
statement''';

If EXPR evaluates to true, then both statement' and statement''
are executed followed by statement'''; otherwise, statement' and
statement'' are skipped and the flow control of the program jumps
to statement'''.

isSuperStar = false;
bonus = 0;

...

if (battingAvg > 300) {
isSuperStar = true;
bonus = 10000;
}
number = 55;

Every if statement can have a corresponding else clause which is executed whenever the if is false (i.e. 0). Syntax.

if (EXPR)
statement';
else
statement'';
statement''';

If EXPR is true, then statement' is executed, the else clause is
skipped and the flow control of the program jumps to statement''';
otherwise, statement' is skipped, statement'' is executed and
the flow control of the program jumps to statement'''.

if (netWorth > 1000000)
cout << "you are rich (with respect to money)";
else
cout << "you are rich in other ways";

An else clause cannot be used without a corresponding if statement. Example.

int i = 10;

...

else   //not allowed -- there is no if statement
cout << "this is not legal\n";

The body of an if construct can be any type of statement. Examples.

if (EXPR) EXPR;      //the body is an expression statement
if (EXPR) return EXIT_SUCCESS;  //body is a return statement
if (EXPR) ;          //body is a null statement
if (EXPR) { }        //body is an empty compound statement
if (EXPR) if (EXPR)  //body is another if statement

An if statement containing another if is referred to as a nested if. There is no limit to the amount of nesting that can occur. Examples.

if (EXPR)
if (EXPR')
statement';
statement'';

If EXPR is true, then EXPR' is evaluated; otherwise,
flow control jumps to statement''.  If EXPR' is evaluated
and it evaluates to true, then statement' is executed;
otherwise, flow control jumps to statement''.

if (age >= 100)
if (gender == 'M')
cout << "old man look at my life";

if (age >= 100)
if (gender == 'M')
if (iq > 120)
cout << "smart old man look at my life";
cout << endl;

When using if statements, it is a good programming practice to use indentation to aid readability. The body of an if statement should be indented three or four spaces.

In all cases, each if can have a corresponding else clause.

if (EXPR)
if (EXPR')
statement';
else
statement'';
statement''';

The top-most  if  does not have an  else  clause, whereas the
inner-most  if  does.  If EXPR evaluates to false, then
flow control jumps to statement'''; otherwise, EXPR' is
evaluated.  If it evaluates to true, then statement' is
executed; otherwise, statement' is skipped and statement'' is
evaluated.  Regardless of which statement is executed,
flow control jumps to statement'''.

Caution is required to make sure that else clauses match up to the correct if construct.

if (age > 100)
if (gender == 'M')
cout << "you are an old man";
else
cout << "you are a young person";

If age is greater than 100, then  if (gender == 'M')  will
be executed.  If the gender is 'M', then the correct statement
will print, but if the gender is not 'M', then the
"you are a young person" message will print.

To correct this problem, a compound statement is needed to
"tie" the  else  clause with the outer-most  if  statement.

if (age > 100) {
if (gender == 'M')
cout << "you are an old man";
} else
cout << "you are a young person";

Now if age > 100, then the body of the  if  is executed;
otherwise, flow control jumps to the  else  clause.

GDT::C++::Code:: Age0.cpp and Age1.cpp and Age2.cpp

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### Logical Operators

Logical operators are used to "connect" expressions. Where relational operators are used to compare two values, logical operators take boolean operands and combine them to form boolean values.

  !     && !expr NOT expr1 && expr2 AND expr1 || expr2 OR

The ! operator is a high-precedence unary operator, while && and || are medium-precedence binary operators. AND has slightly higher precedence than OR.

Examples.

int i = 10, j = 5, k = 0;

i == 10 && j == 5     yields the value 1 (true)
i == 5  && j == 5     yields the value 0 (false)
i == 10 || j == 5     yields the value 1
i == 5  || j == 10    yields the value 0
!i                    yields the value 0
!k                    yields the value 1
!k && k               yields the value 0

Given expr1 && expr2, expr1 is evaluated first. If it evaluates to false, then the entire EXPR will be false (0 && anything is 0); therefore, expr2 is not evaluated. This is called short circuit evaluation.

When using the terms true and false, zero is false and not-zero is true.

GDT::C++::Code:: LogicalOps.cpp

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### Truth Tables and De Morgan's Laws

The following is a "truth table" for the logical operators AND, OR and NOT.

-------------------------------------------------------------------
Logical operators:         AND   OR                            NOT
-------------------------------------------------------------------
expr1       expr2          &&    ||                expr       !expr
-------------------------------------------------------------------
zero        zero           0     0                 zero         1
nonzero     zero           0     1                 nonzero      0
zero        nonzero        0     1
nonzero     nonzero        1     1
-------------------------------------------------------------------
• Typically, a nonzero value implies TRUE and zero represents FALSE.
• AND and OR are binary operators.
• NOT is a unary operator.
• NOT is a "high" precedence operator; AND and OR are "medium" precedence operators.
• NOT has higher precedence than both AND and OR; and AND has a slightly higher precedence than OR

In most popular programming environments, evaluation of a logical expression stops as soon as the truth is known. This is called short circuit evaluation. For example, given the following logical expression.

expr1 || expr2

The C and Java languages guarantee that expr1 is evaluated first. If expr1 evaluates to TRUE, then the entire logical expression is TRUE and expr2 is not evaluated. (TRUE logically OR'd with anything is TRUE.)

The || and && logical operators are sequence points of the language. For example, given the following logical expression.

f() && g()

Function f() is evaluated before function g(); however, the same is not necessarily true given the following arithmetic expression.

f() + g()

Some implementations will evaluate the function f() first, while others will evaluate function g() first.

Logical operators (and the fact that they are sequence points and are subject to short circuit evaluation) are a critical tool when it comes to transaction processing.

step1 && step2 && step3 && commit

don't do step2 if step1 fails
don't do step3 if step2 fails
commit the transaction if step3 is successful
##### De Morgan's Laws

De Morgan's Laws are used to simplify logical expressions.

!(expr1 || expr2)    is equivalent to     !expr1 && !expr2
!(expr1 && expr2)    is equivalent to     !expr1 || !expr2

examples...

useCYMK = !(red || green || blue)
...apply De Morgan's Law...
useCYMK = !red && !blue && !green

isdefective = !(clear && zeroerrors && posted)
...apply De Morgan's Law...
isdefective = !clear || !zeroerrors || !posted

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### A Joke Having To Do With Loops

Example of 21st century Informatics?

Q: How do you keep a computer programmer in the
shower all day long?

A: Give them a shampoo with a label that says
"rinse, lather, repeat."

Berkeley.edu::Jester--The Online Joke Recommender is a "computer program that rates jokes and gives suggestions based on each user's personal sense of humor."

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

### The while Statement

The while statement supports iteration (i.e. it is a repetition control statement). Iteration is the process of repeating an operation.

The idea of looping in a computer program can be attributed to Ada Lovelace (01815-01852). Many believe Lovelace wrote the first "computer program." On 10 December 1980 (Ada's birthday), the U.S. Defense Department approved the reference manual for its new computer programming language, called "Ada".

The while statement repeatedly executes a simple statement or block (i.e. compound statement) until a conditional EXPR becomes false (i.e. 0). Each loop iteration is called a cycle.

while (EXPR)    // typically, you don't want a semicolon
statement;

EXPR is the "conditional" test used to determine whether the loop
should continue for another cycle, and  statement  is to be repeated.
If multiple  statements  need to be executed, then use a compound
statement (or block).

EXPR is evaluated only at the beginning of a loop cycle.

Pseudo-code for a while loop:

top-of-loop
evaluate the EXPR
if  EXPR  is "true"      // i.e. a non-zero value
execute statement
go to top-of-loop
else
go to end-of-loop  (i.e. terminate the loop)
end-of-loop
statement
...

//Example:  loop until user enters a positive number
int n = -1;
while (n <= 0)
cin >> n;

//Example:  print out the numbers 1 through 5
int i = 1;
while (i <= 5) {
cout << i << endl;
i = i + 1;
}
##### Sentinel Values

One way to terminate (end) a loop is when a particular data value is entered (e.g. the user enters a -1 or end-of-file is encountered), a special value that is used to end the loop is called a sentinel value.

Sentinel values should be defined as manifest (symbolic) constants. Example:

const int EXIT_VALUE = -1;
int n = EXIT_VALUE + 1;
while (n != EXIT_VALUE) {
cout << "Enter a number (" << EXIT_VALUE << " to exit): ";
cin >> n;
}
##### Infinite Loops

When you use a loop in a program, it is important to make sure that the condition used to control the loop will eventually become false, so that the loop can end. A loop that never finishes is called an infinite loop.

To stop an infinite loop, a special command sequence must be typed on the keyboard to interrupt the program and forcibly cause it to quit. This command differs from machine to machine.

Sometimes infinite loops are used by design; therefore, existenance of an infinite loop does not necessarily imply a program defect.

// the following are infinite loops that do nothing
while (1)
;  //null statement

int i = 99;
while (i != 0) ;

while (true) ;  //C++ only...

while (!false) { }  //C++ only....

while (43 == 43) ;

{TopOfPage} {Tutorial} {online IDEs: CodingGround | CPP.sh | jdoodle} {C at MIT} {GDT::C/C++ Resource}

Home Previous Next