What We Will Cover
Continuations
Homework Questions?
Problem 1: What is output by the following program? (Do not run the code -- work it out by hand)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream>
using namespace std;
int mystery(int param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
int result = mystery(num);
cout << "After calling, num=" << num << endl;
cout << "And result=" << result << endl;
return 0;
}
int mystery(int param) {
cout << "param=" << param << endl;
param = param * 2;
return param;
}
|
-
At first, num=2
param=2
After calling, num=4
And result=4
-
At first, num=2
param=4
After calling, num=4
And result=4
-
At first, num=2
param=2
After calling, num=2
And result=4
- None of these
^ top
7.1: Advanced Conditions
Learner Outcomes
At the end of the lesson the student will be able to:
- Recognize the correct ordering of tests in multiple branches
- Program conditions using Boolean operators and variables
- Avoid some common pitfalls when creating test conditions
|
^ top
7.1.1: Multiple Alternatives
- By using collections of if-else statements, a program can distinguish between multiple alternatives
- For example, consider the following example from the textbook p. 244 where a user enters the name of a coin, and the program displays the value
Program Converting Coin Names to Values
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <iostream>
using namespace std;
int main() {
cout << "Enter coin name: ";
string name;
cin >> name;
double value = 0;
if (name == "penny") {
value = 0.01;
} else if (name == "nickel") {
value = 0.05;
} else if (name == "dime") {
value = 0.10;
} else if (name == "quarter") {
value = 0.25;
} else {
cout << name << " is not a valid coin name\n";
}
cout << "Value = " << value << "\n";
return 0;
}
|
Choosing Between Alternatives
- This program has five alternatives to choose from:
- "penny"
- "nickel"
- "dime"
- "quarter"
- erroneous input
- Note that the order that the alternatives are checked is unimportant
- We can follow the alternatives in the flowchart shown below
Flowchart of Multiple Alternative for Converting Coins to Values
^ top
7.1.2: When Order Matters
- In some cases, the order of the tests is important
- For example, look at the following program from the textbook that displays a description of the likely impact of an earthquake based on its magnitude on the Richter scale
Program Showing Multiple Alternatives Where Order Matters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include <iostream>
using namespace std;
int main() {
cout << "Enter a magnitude on the Richter scale: ";
double richter;
cin >> richter;
if (richter >= 8.0) {
cout << "Most structures fall\n";
} else if (richter >= 7.0) {
cout << "Many buildings destroyed\n";
} else if (richter >= 6.0) {
cout << "Many buildings considerably damaged, "
<< "some collapse\n";
} else if (richter >= 4.5) {
cout << "Damage to poorly constructed buildings\n";
} else if (richter >= 3.5) {
cout << "Felt by many people, no destruction\n";
} else if (richter >= 0) {
cout << "Generally not felt by people\n";
} else {
cout << "Negative numbers are not valid\n";
}
return 0;
}
|
Order Is Important
- Note that the order of the tests is important to ensure that the right results are printed
- If we rearranged the order of the
if-else statements, we would get the wrong results
- For example, if we reversed the order of the tests:
if (richter >= 0) { // tests in wrong order
cout << "Generally not felt by people\n";
} else if (richter >= 3.5) {
cout << "Felt by many people, no destruction\n";
} else if (richter >= 4.5) {
cout << "Damage to poorly constructed buildings\n";
} else if (richter >= 6.0) {
cout << "Many buildings considerably damaged, "
<< "some collapse\n";
} else if (richter >= 7.0) {
cout << "Many buildings destroyed\n";
} else if (richter >= 7.0) {
cout << "Most structures fall\n";
} else {
cout << "Negative numbers are not valid\n";
}
- This does not work because all values meet the first condition
- Every other test will never be attempted
Importance of Using if-else-if Structure
- Note that we cannot remove the
else portion of the structure like shown below:
if (richter >= 7.0) { // Does not use else
cout << "Most structures fall\n";
}
if (richter >= 7.0) {
cout << "Many buildings destroyed\n";
}
if (richter >= 6.0) {
cout << "Many buildings considerably damaged, "
<< "some collapse\n";
}
if (richter >= 4.5) {
cout << "Damage to poorly constructed buildings\n";
}
if (richter >= 3.5) {
cout << "Felt by many people, no destruction\n";
}
if (richter >= 0) {
cout << "Generally not felt by people\n";
}
if (richter < 0) { {
cout << "Negative numbers are not valid\n";
}
- The conditions must be exclusive and we need the else-if conditions to ensure exclusivity
- Independent
if statements may cause a single input to print several messages
^ top
7.1.3: switch Statements
Example Program Using a switch Statement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
using namespace std;
int main() {
int shippingOption = 0;
cout << "Enter a shipping option (1-3): ";
cin >> shippingOption;
switch (shippingOption - 1) {
case 0:
cout << "Parcel post delivery in two weeks.\n";
break;
case 1:
cout << "UPS delivery in three days.\n";
break;
case 2:
cout << "Fed-Ex overnight delivery.\n";
break;
default:
cout << "It may never get there!\n";
}
cout << "Ship it!\n";
return 0;
}
|
When to Use switch Statements
- You can only use switch statements with integer expressions and each case must be a constant
- In addition, switch statements only work for exact matches (
==)
- Thus,
switch statements are inherently less useful than if-else statements
- Also, the syntax is no clearer than
if-else statements
- Note that there is a reason for the limitations of the
switch statement
- Many years ago a compiler could generate more efficient code (using jump tables or binary searches) only within the limitations of the switch statement
- However, modern compilers are quite capable of optimizing
if-else statements to the same degree
- Thus, we have no reason to ever use a
switch statement, depending on your compiler
- On the other hand, there are reasons to avoid using a
switch statement
- Every branch of the
switch statement must be terminated by a break statement
- If the break statement is missing, the program falls through and executes the next case without testing
- There are rare uses for this fall through behavior, such as printing the words for the song, The Twelve Days of Christmas
- However, according to a study by Peter van der Linden, reported in his book, Expert C Programming, p. 38, the falling through behavior is needed less than 3% of the time
- Thus, the default behavior is wrong 97% of the time
- Forgetting to type the
break statement is a very common error and the source of many bugs
- So one has to ask oneself, "Why use an inferior programming statement that causes more problems than it solves?"
^ top
Exercise 7.1
In this exercise we test multiple alternatives in a program. As an example, we will calculate a student's letter grade according to the following table:
| Numerical Grade |
Letter Grade |
| greater than or equal to 90 |
A |
| less than 90 but greater than or equal to 80 |
B |
| less than 80 but greater than or equal to 70 |
C |
| less than 70 but greater than or equal to 60 |
D |
| less than 60 |
F |
Specifications
- Copy the following program into a text editor, save it as
grader.cpp, and then compile and run the starter program to make sure you copied it correctly.
#include <iostream>
using namespace std;
int main() {
// Enter your code here
return 0;
}
- Add code to get user input into a variable named
score. When you run the program after adding this code, the output should look like:
Enter a score: 95.7
Make sure you declare the variable with a compatible data type. Note that the underlined numbers above shows what the user enters. For more information see section 2.4.6: Input and Output.
- First we will look at a series of
if statements and see that if statements alone are not enough to solve this problem. Copy the following into your program after the input statements:
string grade;
if (score >= 90) {
grade = "A";
}
if (score >= 80) {
grade = "B";
}
if (score >= 70) {
grade = "C";
}
if (score >= 60) {
grade = "D";
}
if (score < 60) {
grade = "F";
}
cout << grade << endl;
Compile and run your modified program. There is a logic problem with this code. Each test condition needs to work over a range of values rather than with a single value.
- One way to correct the problem is to nest an
if statement inside of another if statement. To see how this works, modify your code to add nested if statements as shown below:

To test the range, the outer if statement tests the lower condition and the inner if statement tests the upper condition. For more information see section 7.1.4: Nested Branches.
- Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
Enter a score: 80
B
Run your program a few times with different score to verify that any score displays the correct letter grade.
- The reason for using nested
if statements is often to test multiple conditions. Often, a better alternative is to use Boolean operators like && and ||. To see how Boolean operators work, modify your code to add nested if statements as shown below:

For more information see section 7.1.5: Logical Operators.
- Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
Enter a score: 80
B
Run your program a few times with different score to verify that any score displays the correct letter grade.
- De Morgan's laws lets you use an
|| for the conditions if you reverse the inequalities and precede the test condition with a ! operator. For example, the following is equivalent to the previous example:

Note that this test is more confusing to human's because of the ! (negation) operator. If you have complicated tests such as this, you may be able to use De Morgan's laws to simplify the conditions. For more information see section 7.1.6: De Morgan's Laws.
- Perhaps the most elegant solution is to nest an
if statement in the else clause of the preceding if. Modify the series of if statements to include an else clause as shown below:

We are nesting if statements in the else clause. Nesting in the else clause makes each test condition of the if statement exclusive of the others because each test condition eliminates all the preceding conditions. Thus, in this scenario the order is important. For more information see section 7.1.2: When Order Matters.
- Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
Enter a score: 80
B
Run your program a few times with different score to verify that any score displays the correct letter grade.
- Submit your final program source code to Blackboard as part of assignment 7.
Check Yourself
As time permits, be prepared to answer these questions. You can find more information by following the links after the question.
- True of false? An elegant way to choose among multiple alternatives is to nest
if statements in an else clause. (7.1.1)
- If
score = 85, what is output by the following code fragment? (7.1.1)

- True of false? Order never matters in a sequence of
if and else statements. (7.1.2)
- What is the difference between if-else if-else and nested if statements? (7.1.2 vs. 7.1.4, answer)
- True of false? A switch statement is a more powerful solution to multiple if-else if-else statements (7.1.3)
- When does an AND (
&&) of two or more conditions evaluate to true? (7.1.5)
- When does an OR (
||) of two or more conditions evaluate to false? (7.1.5)
- What is the effect of the NOT (
!) operator? (7.1.5)
- True of false? A && B is the same as B && A for any Boolean conditions A and B. (7.1.5)
- If
score = 85, what is output by the following code fragment? (7.1.5)

- What is the simplified form of each of these using DeMorgan's law? (7.1.6, answer):
!(x > 0 && y > 0)
!(x != 0 || y != 0)
! (country == "USA" && state != "HI" && state != "AK")
!(x % 4 != 0 || !(x % 100 == 0 && x % 400 != 0))
- How many errors can you spot in the following code fragment? (7.1.7)
if (person = terrorist) {
punish_severely();
} else {
exit(-1);
}
Answer and credit for the idea.
- What is wrong with the following string of inequalities and how do you correct the code? (7.1.7)
int a = 5, b = 1, c = 10;
if (a < b < c) {
cout << "b is between a and c\n";
} else {
cout << "b is NOT between a and c\n";
}
- What is wrong with the following string of logical operators and how do you correct the code? (7.1.7)
int guess;
cout << "Enter a guess: ";
cin >> guess;
if (guess == 7 || 8) {
cout << "*** Correct! ***\n";
} else {
cout << "Sorry, that is not correct.\n";
}
^ top
7.1.4: Nested Branches
- Nested
if-else statements can be used when there are two (or more) levels of decision making.
- For example, consider the following two tax tables from 1992 shown in the textbook on p. 252
- There is a different table for each marital status (decision 1)
- Once you have found the right table, your are taxed differently according to your income (decision 2)
Tax Table if Single
| If your status is Single and if the taxable income is over |
but not over |
the tax is |
of the amount over |
| $0 |
$21,450 |
15% |
$0 |
| $21,450 |
$51,900 |
$3,217.50 + 28% |
$21,450 |
| $51,900 |
|
$11,743 + 31% |
$51,900 |
Tax Table if Married
| If your status is Married and if the taxable income is over |
but not over |
the tax is |
of the amount over |
| $0 |
$35,800 |
15% |
$0 |
| $35,800 |
$86,500 |
$5,370.00 + 28% |
$35,800 |
| $86,500 |
|
$19,566.00+ 31% |
$86,500 |
Programming Two-Level Decisions
- When we program this two-level decision process, we often use two levels of
if statements
- We say the income test is nested inside the test for filing status
- We can see this two-level decision in the flowchart shown below
- Also, we can examine and run the program from the code shown below
- Note that more complicated decisions may require deeper levels of nesting
Flowchart of Two-level Tax Decision Process
Program Computing Single and Married Tax Rates
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#include <iostream>
using namespace std;
int main() {
const double SINGLE_LEVEL1 = 21450.00;
const double SINGLE_LEVEL2 = 51900.00;
const double SINGLE_TAX1 = 3217.50;
const double SINGLE_TAX2 = 11743.50;
const double MARRIED_LEVEL1 = 35800.00;
const double MARRIED_LEVEL2 = 86500.00;
const double MARRIED_TAX1 = 5370.00;
const double MARRIED_TAX2 = 19566.00;
const double RATE1 = 0.15;
const double RATE2 = 0.28;
const double RATE3 = 0.31;
double income;
double tax;
cout << "Please enter your income: ";
cin >> income;
cout << "Please enter s for single, m for married: ";
string marital_status;
cin >> marital_status;
if (marital_status == "s") {
if (income <= SINGLE_LEVEL1) {
tax = RATE1 * income;
} else if (income <= SINGLE_LEVEL2) {
tax = SINGLE_TAX1
+ RATE2 * (income - SINGLE_LEVEL1);
} else {
tax = SINGLE_TAX2
+ RATE3 * (income - SINGLE_LEVEL2);
}
} else {
if (income <= MARRIED_LEVEL1) {
tax = RATE1 * income;
} else if (income <= MARRIED_LEVEL2) {
tax = MARRIED_TAX1
+ RATE2 * (income - MARRIED_LEVEL1);
} else {
tax = MARRIED_TAX2
+ RATE3 * (income - MARRIED_LEVEL2);
}
}
cout << "The tax is $" << tax << "\n";
return 0;
}
|
^ top
7.1.5: Logical Operators
- An operator that combines test conditions is called a logical operator or Boolean operator
- Logical operators allow you to consider multiple cases when deciding on what code to execute
- Being able to consider multiple cases gives us more flexibility in creating test conditions
- C++ has several logical operators, but you only need to use three to create any possible Boolean expression
- These three operators are
and, or and not, which are discussed below
- These logical operators are traditionally written as
&& (and), || (or) and ! (not)
- Both variants are legal under ANSI C++
- The words are easier to read but many C++ programmers still use the older form
and Operation
or Operation
not Operation
Parenthesis
Confusing && and || Conditions
- Many people confuse
&& and || conditions, especially when learning about logical operators
- A value lies between 0 and 100 if the value is at least 0 and at most 100
- A value is outside that range if it is less than 0 or greater than 100
- There is no golden rule; you have to think carefully and test your conditions
Example Program with Logical Operators
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <iostream>
using namespace std;
int main() {
const int ANSWER1 = 7;
const int ANSWER2 = 8;
int guess = 0;
cout << "I'm thinking of a number between"
<< " 1 and 10.\nCan you guess it?\n\n"
<< "Enter your guess: ";
while (guess != ANSWER1 && guess != ANSWER2) {
cin >> guess;
if (ANSWER1 == guess || ANSWER2 == guess) {
cout << "*** Correct! ***\n";
} else {
cout << "Sorry, that is not correct.\n";
cout << "Try again: ";
}
}
return 0;
}
|
^ top
7.1.6: De Morgan's Laws
- Suppose we want to charge a higher shipping rate if we do not ship to the continental United States
- We might code a conditional statement like:
if (!(country == "USA"
&& state != "AK"
&& state != "HI")) {
shipping_charge = 20.00;
}
- This test is somewhat complicated and we have to think carefully through the logic
- What makes the test complicated is the multiple not ('
!') operators
- Humans generally have a hard time comprehending logical conditions with not operators ('
!') applied to and/or expressions
- DeMorgan's Law can be used to simplify these Boolean expressions
- DeMorgan's Law has two forms:
!(A && B) is the same as !A || !B
!(A || B) is the same as !A && !B
- Pay particular attention to the fact that the
&& and || operators are reversed by moving the ! (not) inwards
- For example:
state != "AK" && state != "HI"
means:
!(state == "AK") && !(state == "HI")
- Applying DeMorgan's Law to the original expression yields:
!(state == "AK" || state == "HI")
- Applying DeMorgan's Law to our original problem:
!(country == "USA"
&& state != "AK"
&& state != "HI"))
which is equivalent to:
!(country == "USA"
|| !(state != "AK")
|| !(state != "HI"))
Which in turn yields the simpler test:
country != "USA"
|| state == "AK"
|| state == "HI"
More Information
^ top
7.1.7: Conditional Pitfalls
- Unfortunately, you can write many things in C++ that should be incorrect but end up working for some obscure reason
- This means that you can code something that should create an error message but does not
- Thus, a program may compile and run with no error messages but still be wrong
- Since you may not realize that it is wrong, it can be hard to find and correct these types of errors
Using = Instead of ==
- One common mistake is to use
= when you meant to use ==
- For example, look at the test condition in the following code:
if (guess = 7) {
cout << "*** Correct! ***\n";
} else {
cout << "Sorry, that is not correct.\n";
}
- Notice that the condition is really an assignment statement and not a test
- You would think that it would fail to compile -- but it does not
- However, it will not work as you might expect
- A way to prevent this type of problem is to reverse the order of your test condition:
if (7 = guess) {
- Now the compiler will give you an error message and your code will not compile:
guess.cpp: In function `int main()':
guess.cpp:10: error: non-lvalue in assignment
- However, if you correctly use == then your code will compile
if (7 == guess) {
Strings of Inequalities
- Do not use a string of inequalities like the following:
int a = 5, b = 1, c = 10;
if (a < b < c) {
cout << "b is between a and c\n";
} else {
cout << "b is NOT between a and c\n";
}
- Your code will probably compile and run but give incorrect results
- Instead, the correct way is to use
&& as follows:
int a = 5, b = 1, c = 10;
if (a < b && b < c) {
cout << "b is between a and c\n";
} else {
cout << "b is NOT between a and c\n";
}
Strings of Logical Operators
- Logical expressions often read like "normal" English.
- However, C++ requires more exactness than English
- For example, the following code will compile and run but give wrong results:
int guess;
cout << "Enter a guess: ";
cin >> guess;
if (guess == 7 || 8) {
cout << "*** Correct! ***\n";
} else {
cout << "Sorry, that is not correct.\n";
}
- Instead, the correct way is to use
|| as follows:
int guess;
cout << "Enter a guess: ";
cin >> guess;
if (guess == 7 || guess == 8) {
cout << "*** Correct! ***\n";
} else {
cout << "Sorry, that is not correct.\n";
}
^ top
7.1.8: Summary
if (guess = 7) {
Another problem is trying to use a string of inequalities without a logical operator separating each condition
if (a < b < c) {
Which should be written as:
if (a < b && b < c) {
Another error is trying to use logical operators without enough operand
if (guess == 7 || 8) {
Which should be written as:
if (guess == 7 || guess == 8) {
^ top
7.2: Advanced Loops
Learner Outcomes
At the end of the lesson the student will be able to:
- Discuss when to use which C++ looping statement
- Process user input in a loop
- Read input from a file through redirection
- Discuss why to avoid
break and continue statements with loops
|
^ top
7.2.1: Comparing C++ Looping Statements
- Recall that C++ has three looping statements:
for: special purpose counting loop
while: general purpose loop
do-while: like the while but testing at the end of the loop
- When we design a loop, we need to consider these things:
- Loop body -- which statements to repeat
- Test condition -- when to loop and when to stop
- Test update -- what must change to exit the loop
- Initialization code -- how to start the loop correctly
- The
for loop provides a syntax for these things in a compact form:
for (initialization; test; update) {
// statements to repeat
}
- Where:
- initialization: statement to execute before the loop starts
- test: condition to evaluate at the start of each iteration
- update: statement to execute at the end of the loop
- The
for loop is primarily used for counting:
for (int i = 0; i < 10; i++) {
cout << i << endl;
}
- The simpler
while loop has the following syntax:
while (test) {
// statements to repeat
}
- Where test is the condition to evaluate at the start of each iteration
- Because of its simpler form, the
while loop is considered a more general purpose loop
- However, we still have to include the four parts of a loop design:
string repeat = "y"; // initialization
while ("y" == repeat) { // test condition
// statements to repeat
cin >> repeat; // update
}
- Another looping statement is the
do-while loop, which tests the condition at the end of the loop body:
do {
// statements to repeat
} while (test); //test condition
- Where test is the condition to evaluate at the end of each iteration
- Testing at the end ensures a minimum of at least one iteration
- Thus we use the
do-while loop when we want to ensure at least one iteration
- For example:
string repeat; // no initialization needed
do {
// statements to repeat
cin >> repeat; // update
} while ("y" == repeat); // test condition
Which Loop Statement to Use
- Generally, we use
for statements when counting with a loop
- For non-counting loops where we want to ensure at least one iteration, use a
do-while statement
- Otherwise, use the simpler
while statement
- Notice that all loops have the same test condition
- This makes it possible always to convert one looping statement into another with some adjustment to other code
- Thus, choosing which loop statement to use is more a matter of elegance than a requirement
^ top
7.2.2: Nested Loops
- More advance looping applications often have loops nested within other loops
- For example, you may use a nested loop to print a table of values
- The following example shows a simple table created with nested loops
- Let's follow the execution sequence before checking the result
Example of Nested Loops
1
2
3
4
5
6
7
8
9
10
|
#include <iostream>
using namespace std;
int main() {
for (int outer = 1; outer < 4; outer++) {
for (int inner = 1; inner < 4; inner++) {
cout << outer << " " << inner << endl;
}
}
}
|
Tracing the Variables
- Below is a trace of the variables for the inner and outer loops
- Note that the outer loop changes only after the inner loop is finished
| Memory |
Screen |
int outer
| int inner
|
|
1 |
1 |
1 1 |
| |
2 |
1 2 |
| |
3 (end of loop) |
1 3 |
2 |
1 |
2 1 |
| |
2 |
2 2 |
| |
3 (end of loop) |
2 3 |
3 (end of loop) |
1 |
3 1 |
| |
2 |
3 2 |
| |
3 (end of loop) |
3 3 |
^ top
7.2.3: Accumulating Values
- Consider a program to sum series of numbers from the keyboard
- The program uses a variable (
sum) to accumulate values entered from the keyboard each time through the loop
Example Program to Sum a Series of Numbers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <iostream>
using namespace std;
int main() {
double input = 1;
double sum = 0;
cout << "I will add up numbers for you\n\n";
while (input != 0) {
cout << "So far, sum = " << sum << endl;
cout << "Enter a number or 0 to exit: ";
cin >> input;
sum = sum + input;
}
cout << "Ending sum: " << sum << endl;
return 0;
}
|
Redirection of Input and Output
^ top
7.2.4: Using break and continue Statements with Loops
- We saw the use of the
break statement in the switch statement
- Another use the
break statement is to terminate loops
- The
continue statement is similar except that instead of exiting a loop, it jumps to the end of the loop
- The causes the loop to skip the rest of the current iteration and start the next iteration
- The following code shows an example of
break and continue
- Note that using
break and continue statements with loops is generally consider poor programming style
- The reason we are reviewing them is to see what NOT to do
Example Using the break and continue Statements
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <iostream>
using namespace std;
int main() {
int count = 0;
while (true) {
count++;
if (count == 3) {
continue;
}
cout << count << endl;
if (count >= 5) {
break;
}
}
cout << "After count= " << count << endl;
}
|
When to Use break and continue Statements
- Use
break statements in switch statements only
- For this course, never use
break or continue statements in looping constructs:
- Poor coding habit
- Loops should only have one exit point
- Note that the textbook on p. 137 has an interesting story about a major problem caused by the use of
break statements
- On January 15, 1990, a misused
break statement caused an AT&T 4ESS telephone switch to fail
- The failure propagated through the entire U.S. network, rendering it nearly unusable for about nine hours
- A programmer had used a
break to terminate an if statement
- However,
break cannot be used to break out of an if
- Therefore the program execution broke out of the enclosing
switch statement instead
- Perhaps more importantly, using a
break statement makes it difficult to prove program correctness in critical software
^ top
7.2.5: Summary
- C++ has three looping statements:
for: special purpose counting loop
while: general purpose loop
do-while: like the while but testing at the end of the loop
- The
for loop is primarily used for counting:
for (int i = 0; i < 10; i++) {
cout << i << endl;
}
- We use the
do-while loop when we want to ensure at least one iteration, like:
string repeat; // no initialization needed
do {
// statements to repeat
cin >> repeat; // update
} while ("y" == repeat); // test condition
- Otherwise, use the simpler
while statement:
string repeat = "y"; // initialization
while ("y" == repeat) { // test condition
// statements to repeat
cin >> repeat; // update
}
- Sometimes you need to nest one loop inside another
- We looked at an example of building a table using nested loops
- The outer loop iterated through the columns while the inner loop iterated through the row
- We looked at how to process user input using a loop
- Also, we looked at how to use a file with input redirection
- We can redirect program input from a file, program output to a file or both:
scores < input.txt
scores > output.txt
scores < input.txt > output.txt
- In addition, we looked at how to use break and continue with loops
- Then we discussed why you should not use break and continue with loops
^ top
Exercise 7.2
In this exercise we explore the uses of loops to process user input.
Specifications
- Copy the following program into a text editor, save it as
scores.cpp, and then compile and run the starter program to make sure you copied it correctly.
#include <iostream>
using namespace std;
int main() {
// Enter your code here
return 0;
}
- Declare two variables of type
double named sumScores and nextScore and initialize the variables to 0. In addition, declare an integer variable named count and initialize it to 0. Compile your code to make sure you declared the variables correctly.
- Now we want to use a loop to enter a series of scores. Add the following code after the variables you declared:
do {
count++;
cout << "Enter score #" << count << ": ";
cin >> nextScore;
if (nextScore >= 0) {
sumScores += nextScore;
}
} while (nextScore >= 0);
Compile your code to make sure you added the loop correctly.
- The loop includes statements to collect the sum of the scores in the variable named
sumScores. Add a statement after the loop to print sumScores to the console. When you run the program after adding this code, the output should look like:
Score 1: 38
Score 2: 39
Score 3: -1
Sum of scores: 77
The loop uses the sumScores variable to accumulate scores during each repetition of the loop. For more information see lesson: 5.1.5: Accumulating Values.
- Each assignment can have a different value and we need to allow for the different values. First you will need to add two variables of type
double named sumValues and nextValue after the other variables. Then update the loop with the following code:

Compile your code to make sure you updated the loop correctly. Notice how one if statement is nested inside another. For more information see section: 7.1.4: Nested Branches. Also notice the compound condition joined by the logical operator &&. For more information see section: 7.1.5: Logical Operators
- The loop has statements to collect both the sum of the scores in the variable named
sumScores and the sum of the values in the variable named sumValues. Add a statement after the loop to print both sumScores and sumValues to the console. When you run the program after adding this code, the output should look like:
Score 1: 38
Value of score 1: 40
Score 2: 39
Value of score 2: 40
Score 3: -1
Sum of scores: 77
Sum of values: 80
- The grade for all the scores is calculated by dividing the sum of the scores by the sum of the values. Add these statements after the other print statements:
double percentage = sumScores / sumValues * 100;
cout << "Grade percentage: " << percentage << endl;
When you run the program after adding this code, the output should look like:
Score 1: 38
Value of score 1: 40
Score 2: 39
Value of score 2: 40
Score 3: -1
Sum of scores: 77
Sum of values: 80
Grade percentage: 96.25
- One problem with our program is the user can still enter letters instead of digits. We can prevent this error by checking
cin.fail() and looping until the user enters a correct value. We implement this loop in a function to make a reusable module by using the following code:

Compile your program to make sure you added the new function correctly. Notice how the while loop of inputDouble() is nested inside the do-while loop of main(). Nesting loops is often confusing and so we sometimes put the inner loop in a separate function. For more information see section: 7.2.2: Nested Loops.
- To use the inputDouble() function, we need to change two statements in main. Change
cin >> nextScore; to:
nextScore = inputDouble();
Also, change cin >> nextValue; to
nextValue = inputDouble();
- Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
Score 1: thirty-eight
Error: please enter a number: 38
Value of score 1: forty
Error: please enter a number: 40
Score 2: 39
Value of score 2: 40
Score 3: -1
Sum of scores: 77
Sum of values: 80
Grade percentage: 96.25
- Next we use input and output redirection to both enter values into and save the output of your program. Save the following file to the same directory as your program source code:
input.txt
Then run your compiled program by typing the following at the command line:
./scores < input.txt > output.txt
Open output.txt in a text editor like TextPad and notice how scrambled the input statements look. However, the output should look normal. For more information see section: 7.2.3: Accumulating Values.
- Submit both your final program source code and
output.txt to Blackboard as part of assignment 7.
Check Yourself
As time permits, be prepared to answer these questions. You can find more information by following the links after the question.
- What are the advantages of using a
for loop compared to other looping statements? (7.2.1)
- What is the difference between a
while and a do-while loop? (7.2.1)
- When should you use each type of loop statement supported by C++? (7.2.1)
- What is a nested loop? (7.2.2)
- What is input and output redirection and when should you use it? (7.2.3)
- Why should you avoid using break and continue statements with loops? (7.2.4)
^ top
7.3: Reference Parameters
Learner Outcomes
At the end of the lesson the student will be able to:
- Explain the difference between call-by-value and call-by reference parameter passing
- Return values from functions using call-by-reference
|
^ top
7.3.1: Parameter Passing and Value Parameters
- There are two ways to pass arguments to parameters
- All our functions so far have used value parameters
- Value parameters are separate variables from the ones in
main() (or another calling function)
- Modification of value parameters does not affect the original value
How Value Parameters Work
- During the function call, your program copies the argument value into the parameter variable
- The scope of value parameters is the same as for a local variable
- If modified, only the local copy changes
- When the function returns, your program discards any value assigned to the parameter
- The following example program uses value parameters
- What does this program output?
Example of Value Parameters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream>
using namespace std;
int mystery(int param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
int result = mystery(num);
cout << "After calling, num=" << num << endl;
cout << "And result=" << result << endl;
return 0;
}
int mystery(int param) {
cout << "param=" << param << endl;
param = param * 2;
return param;
}
|
^ top
7.3.2: Reference Parameters
Example of Reference Parameters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream>
using namespace std;
int mystery(int& param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
int result = mystery(num);
cout << "After calling, num=" << num << endl;
cout << "And result=" << result << endl;
return 0;
}
int mystery(int& param) {
cout << "param=" << param << endl;
param = param * 2;
return param;
}
|
Call-By-Reference Details
- What's really passed to the reference parameter?
- A reference to the caller's original argument!
- A reference is the memory address of a variable
- Note that arguments for reference parameters must be variables and not constants
^ top
7.3.3: Mixed Parameter Lists
- You can combine parameter-passing mechanisms in one function
- Parameter lists can include both value and reference parameters
- As usual, the order of arguments in the list is critical
- The following is the function prototype with mixed parameter types:
void mixedCall(int& par1, int par2, double& par3);
- To call the function:
int arg1 = 0, arg2 = 1;
double arg3 = 2.2;
mixedCall(arg1, arg2, arg3);
arg1 must be an integer type and is passed by reference
arg2 must be an integer type and is passed by value
arg3 must be a double type and is passed by reference
^ top
7.3.4: When to Use Reference Parameters
- Reference parameters are more efficient than value parameters because they do not make copies of the parameters:
- A program simply passes the memory address to the function
- No new memory space is allocated and deallocated
- Therefore, procedure calls using reference parameters usually operate faster
- However, reference parameters restrict the arguments you can use for your function
- Specifically, you must use a variable argument and not a literal or constant value
- Usually, the best practice is to pass an object by reference
- Also, you pass a primitive type by reference only when a function needs to modify a parameter
- Otherwise, you usually do not bother passing primitive types by reference
- The performance advantage of reference parameters for primitive types tends to be negligible
- Thus, it is not worth restricting the call pattern of your function
- The following example uses a reference parameter for the object type and a value parameter for the primitive type
Example Program Using Mixed Parameters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include "turtlelib.cpp"
void drawSquare(Turtle& turtle, double size);
int ccc_win_main() {
Turtle myrtle;
myrtle.right(90);
drawSquare(myrtle, 3);
myrtle.moveTo(-6, -6);
drawSquare(myrtle, 5);
return 0;
}
void drawSquare(Turtle& turtle, double size) {
const double ANGLE = 90;
turtle.forward(size);
turtle.left(ANGLE);
turtle.forward(size);
turtle.left(ANGLE);
turtle.forward(size);
turtle.left(ANGLE);
turtle.forward(size);
turtle.left(ANGLE);
}
|
^ top
Exercise 7.3
In this exercise we explore how call-by-reference parameters differ from call-by-value parameters.
Specifications
- Type the following program into a text editor and save it as
swap.cpp:

- Compile and run the starter program to make sure you entered it correctly. When you run the program, the output should look like this:
Enter two integers: 1 2
After calling function: 1 2
Notice that num1 and num2 have the same values before and after calling the function swap(). Any value assigned to var1 and var2 have no effect on num1 and num2. For more information, see section: 7.3.1: Parameter Passing and Value Parameters.
- Change your program by adding the four ampersands (&) circled below:

The ampersands tell C++ to use call-by-reference when passing parameter values. For more information, see section: 7.3.2: Using Reference Parameters.
- Compile and run the modified program to make sure you made the changes correctly. When you run the program, the output should look like this:
Enter two integers: 1 2
After calling function: 2 1
Notice that num1 and num2 have different values before and after calling the function swap(). Any value assigned to var1 and var2 change num1 and num2 respectively. For more information, see section: 7.3.2: Using Reference Parameters.
- Submit your final program source code to Blackboard as part of assignment 7.
Check Yourself
As time permits, be prepared to answer these questions. You can find additional information in the sections that follow.
- When an argument is passed to a value parameter, what gets copied? (7.3.1)
- When an argument is passed to a reference parameter, what gets copied? (7.3.2)
- How do call-by-value and call-by reference differ? (7.3.1 and 7.3.2)
- Can you mix call-by-value and call-by-reference in the same parameter list? (7.3.3)
- When should you use reference parameters? (7.3.4)
- When should you use value parameters? (7.3.4)
^ top
7.3.5: Summary
^ top
7.4: Midterm Preparation
Learner Outcomes
At the end of the lesson the student will be able to:
- Discuss how to prepare for the midterm exam
- Describe how to take the midterm exam
|
^ top
7.4.1: About the Exam
- You must attend the exam or you will receive a score of zero (0)
- Except by prior arrangement with the instructor
- I am using Blackboard to administer the test
- Since there are more students than computers, we must take the exams in shifts
- Shifts are determined by your last name and section as follows:
| Last Name
| Section |
Start Time |
| A-G |
Day |
10:20 AM |
| H-Z |
Day |
11:20 AM |
| A-M |
Evening |
6:00 PM |
| N-Z |
Evening |
8:00 PM |
- If you want to change shifts then make arrangements to switch with another student who is on the other shift
- The exam is closed books and closed notes
- However, you may have one 3" x 5" card of handwritten notes for the exam
- You may use a computer from the classroom, but only to take the exam in Blackboard
- You may have a sheet of blank scratch paper
- You may NOT use the computer to compile or run programs
- You may NOT use the computer to view documents on the Internet
- You may NOT use a calculator or other electronic device
- Thus, you may NOT use your own computer to take the exam
- If you have a cell phone visible or in use during the exam, you will automatically fail
- You may NOT communicate with anyone but the instructor during the exam
3"x5" Card Requirements
- Put your name on your card
- Maximum card or paper size is 3 inches by 5 inches
- You may use both sides of the card
- Notes must be handwritten and NOT photocopied
- Notes cannot have any complete functions -- only code snippets
- Any 3" x 5" cards violating these rules will be confiscated before the test
- You must turn in your 3" x 5" card after the exam in any case
^ top
7.4.2: Recommended Preparation
- Try the Example Midterm in Blackboard
- These questions are intended to help you get a "feel" for taking an exam in Blackboard
- The questions are NOT intended to tell you everything that is on the exam
- Review the instructor's notes and make sure you can answer the Check Yourself questions, making notes about anything that you have difficulty answering
- Review your notes and prepare your 3" x 5" card
- Review your homework assignments and solutions
- Review your CodeLab exercises
- You should be prepared to write short programs
- Mathematical expressions
- User I/O
- Conditional statements
- Testing multiple conditions
- "main" loops
- Counting loop algorithms such as accumulating values in a loop
- Using library functions (
pow(), rand(), sqrt(), etc.)
- Declaring and defining functions
- Call-by-value
- Call-by-reference
- More quiz tips: Basic Rules For Taking a Multiple-Choice Test
^ top
7.4.3: Exam Taking Tips
- Save after every answer -- you can change your mind and choose another
- If you get stuck on a question, make your best guess and return later
- If you are equally uncertain between two choices, go with first impression
- When writing code, do NOT add more than the problem asks for
- You do not need to comment code for tests and exams
- Unless specifically instructed to in the exam question
- Use the full time available
- Check your work if you finish early
^ top
7.4.4: Questions and Answers
^ top
Wrap Up
^ top
Home
| Blackboard
| Announcements
| Day Schedule
| Eve Schedule
Course info
| Help
| FAQ's
| HowTo's
| Links
Last Updated: April 21 2009 @14:17:51
|