Home Previous Next

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

Overview

Assignments:

Code: [arithmetic review] arithmetic.cpp | years.cpp | {years2.cpp and years3.cpp} Expressions0.cpp | Expressions1.cpp
[if-else review] if.cpp | if2.cpp | calc.cpp | generations.cpp | Age0.cpp {Age1.cpp and NewAge.cpp}
[logical operators] ifcode.cpp | andor.cpp | Age2.cpp
[loops] Adder.cpp | f10while.cpp | f10while2.cpp

### 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."
```

{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}

### The `do while` Statement

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

The `do 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.

```   do
statement;
while (EXPR);  //semicolon must follow the while 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).  A compound statement is almost always used.

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

Pseudo-code for a do-while loop:

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

//Example:  print out the numbers 1 through 3
int i = 1;
do {
cout << i << endl;
i = i + 1;
} while (i <= 3);

Could the previous loop be rewritten:
int i = 1;
do cout << i++ << endl; while (i <= 3);

int i = 1;
do cout << i << endl; while(i++ <= 3);
```

When you know for sure that a loop must cycle at least once, then a do-while is a good loop construct to use.

```   set item counter to 0
do {
prompt user for data
get data from user
if (data equals sentinel value)
break;
if (data is junk)
continue;  //get more data from the user
process the data
increment the item counter
} while (1);
print the item counter
```
##### Comment on Style

The `do-while` can be difficult to read; therefore, to help it "stick" out, I suggest the following.

• place the `do` on a line by itself
• always use a compound statement
• the body of the loop should be indented (of course)
• place the closing `while` on a line by itself

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

### The `for` Statement

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

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

```   for ([initialization-step]; [conditional-step]; [increment-step])
statement;

The optional "initialization-step" is executed once before the loop
is ever executed (and before the "conditional-step" is evaluated
for the first time).

The optional "conditional-step" is an EXPR that is evaluated at
the top of the loop.  If it is true, then the body of the
for  statement is executed; otherwise, flow control jumps to
the first executable statement after the  for  loop body.  If
no conditional-step is specified, then  it is taken as
permanently true.

After the body of a  for  loop has been executed, the optional
"increment-step" is executed.

After the increment-step is executed; the conditional-step
is re-evaluated.

Example:

//print the numbers 1 through 3

int i;
for (i = 1; i <= 3; i = i + 1)
cout << i << endl;
```

If the body of the `for` contains multiple statements, then a compound statement is needed.

All three steps for a `for` loop are EXPRs. Most commonly, the initialization-step and the increment-step are assignments or functions calls, and the conditional-step is a relational EXPR.

The `for` is frequently used when there are simple initialization and increment steps because it keeps the loop control statements close together and visible at the top of the loop.

The initialization and increment steps often take advantage of the `sequence` operator.

```   for (i = 0, j = 99; i < n; i = i + 1, j = j - 1)
do_something;
```

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

### The `break` Statement

The `break` statement is a jump control statement that is used inside of repetition control statements and the `switch` selection control statement.

The `break` statement causes an immediate exit from the innermost enclosing `switch` or loop statement.

The `break` statement allows a loop to be exited from some point other than at the top or bottom of the loop.

Structured programming purist are not overly fond of the `break` statement.

```   //
// enter into an infinite loop reading integers entered by
// the user... the loop terminates when a sentinel value of
// -1 is entered...
//
int cnt = 0;
const int SENTINEL = -1;
while (1) {
cout << "Enter an integer (" << SENTINEL << " to exit): ";
cin >> input;
if (SENTINEL == input)
break;  //flow control jumps to the statement A
cnt = cnt + 1;
...
}
/*A*/ cout << cnt << " numbers entered" << endl;
```

You must be careful when you use the `break`.

```   while (...) {
...
if (...) {
...
if (...)
break;  // the programmer wants to  break  out of the
// body of the enclosing  if  statement,
// but instead the  break  will cause the
// the 1st executable statement after the
// body of the  while  statement (/*B*/)
...
}
/*A*/ ...
}
/*B*/ ...
```

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

### The `continue` Statement

The `continue` statement is a jump control statement that is used inside of repetition control statements.

The `continue` statement causes the next iteration of the enclosing loop statement to begin. In the `while` and `do` this means that the control-EXPR is executed immediately; in the `for` control passes to the step-EXPR.

The `continue` statement is often used when the part of the loop that follows is complicated, so that reversing a test and indenting another level would nest the program too deeply.

Structured programming purist are not overly fond of the `continue` statement.

```   while (input != SENTINEL) {
/* Part A */
...

if (EXPR)
continue;

/* Part B */
...
}

When  if (EXPR)  evaluates to  true,  the  continue  statement
is executed and the flow control of the program jumps to
control expression of the  while  (i.e.  input != SENTINEL)
is re-evaluated.
```

Here is the same loop written without using a `continue` statement.

```   while (input != SENTINEL) {
/* Part A */
...

if (!EXPR) {
/* Part B */
...
}
}
```

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

### The `goto` Statement

The `goto` statement is a jump control statement that is used to alter the flow control of a program.

Statements can labeled. Label names conform to the naming syntax that is applied to variables. Syntax of a labeled statement.

```   some_label_name:  statement;
```

Statement labels are used with the `goto` statement.

```   goto some_label_name;
```

When a `goto` is executed, the flow control of the program immediately jumps to the labeled statement.

Although use of the `goto` should be minimized, there are a few situations where they may be useful.

```   for (EXPR) {
...
for (EXPR) {
...
if (EXPR)
goto end_of_loops;  /*want to break from both loops*/
...
}
...
}
end_of_loops:
...
```

An aside: In Java, `goto` is not a keyword, but it is a reserved word. In addition, to handle the aforementioned example, Java supports labeled `break` statements.

The `goto` statement is frequently found in code that is generated by other programs.

If you want to go somewhere, goto is the best way to get there.
-- Ken Thompson (creator of Unix)

Edsger Dijkstra (01930-02002) was a Dutch computer scientist. Dijkstra won the ACM Turing Award in 01972. According to the Wikipedia, Dijkstra was also known for his "low opinion of the GOTO statement in computer programming, culminating in the 1968 article 'A Case against the GO TO Statement', regarded as a major step towards the widespread deprecation of the GOTO statement and its effective replacement by structured control constructs such as the while loop. This methodology was also called structured programming." {Wikipedia.org::Edsger W. Dijkstra}

##### Update::2016.12.19

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

Home Previous Next