What We Will Cover
Continuations
Homework Questions?
Questions from last class?
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
|
#include <iostream>
using namespace std;
int mystery(int param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
num = mystery(num);
cout << "Later, num=" << num << endl;
return 0;
}
int mystery(int param) {
cout << "param=" << param << endl;
param = param * 2;
return param;
}
|
-
At first, num=2
Later, num=2
-
At first, num=2
param=2
Later, num=2
-
At first, num=2
param=2
Later, num=4
- None of these
^ top
6.1: More Control Statements
Objectives
At the end of the lesson the student will be able to:
- Use
switch statements for branching
- Use
do-while statements to control loops
- Use
for statements to control loops
- Use
break and continue statements with loops
|
- In this section, we learn about the rest of C++'s control statements
- These statements do not add new capabilities
- Just provide alternate ways of performing some tasks
- Since C++ code has them, you need to know how to use them
^ top
6.1.1: switch Statements
- The
switch statement provides an alternative to an if-else chain
- Executes a section of code depending on value of a variable
- General form:
switch (integerExpression) {
case label1:
statements
break;
case label2:
statements
break;
...
case labeln:
statements
break;
default:
statements
break;
}
Keyword switch identifies the start of the switch statement
Expression in parenthesis is evaluated for comparison to each case label
integerExpression must evaluate to an integer
- Otherwise a compilation error occurs
Within a switch statement, keyword case labels each entry point into the code
- Code executes if
integerExpression matches the case label value
- Execution starts with the statement immediately following the match
Any number of case labels can be placed in any order
Any value that does not match starts executing with the statement after default
Execution continues until the end of the switch statement or a break statement
The break statement causes an immediate exit from the switch statement
Just as case identifies possible starting points, break determines end points
For Example:
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
|
#include <iostream>
using namespace std;
const int PARCEL_POST = 0;
const int UPS = 1;
const int FED_EX = 2;
int main() {
int shippingOption = UPS;
cout << "Enter a shipping option: ";
cin >> shippingOption;
switch (shippingOption) {
case PARCEL_POST:
cout << "Delivery in two weeks.\n";
break;
case UPS:
cout << "Delivery in three days.\n";
break;
case FED_EX:
cout << "Overnight delivery.\n";
break;
default:
cout << "It may never get there!\n";
}
cout << "Ship it!\n";
return 0;
}
|
- Notice that each
case other than the last contains a break statement
- Ensures that the
switch statement is exited after a matching case is found
When to Use switch Statements
- You can only use switch statements with integer expressions
- Inherently less useful than
if-else statements
- Syntax is no clearer than
if-else statements
- Thus, no real need to ever use a switch statement
^ top
6.1.2: Conditional (Ternary) Operators
- Provides a compact
if-else structure
- Syntax:
operand1 ? operand2 : operand3;
First operand must be a conditional expression that evaluates to true or false
If operand1 is true, return operand2; otherwise return operand3.
For Example
- Following is an if-else statement
string outMessage;
int celsius;
cout << "Enter the Celsius temperature: ";
cin >> celsius;
if (celsius >= 100) {
outMessage = "Boiling!";
} else {
outMessage = "Not boiling";
}
cout << outMessage << endl;
Equivalent using the conditional operator
string outMessage;
int celsius;
cout << "Enter the Celsius temperature: ";
cin >> celsius;
outMessage = (celsius >= 100)
? "Boiling!"
: "Not boiling";
cout << outMessage << endl;
When to Use Conditional (Ternary) Operators
- Rarely used in professional programing
- Almost always clearer to use
if-else statements
^ top
6.1.3: do-while Statements
- Variation of the
while loop
- Syntax:
//Initialization
...
do {
//loop body
...
} while (loopTest); //loop condition
Initialization code may precede loop body
Loop test is after the loop body
Loop must execute at least once (minimum of at least one iteration)
Use when you want to force a minimum of one iteration
Validity Checks
- You can use
do-while statements to filter user input
- For example, assume we need a positive value from the user:
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() {
//Loop initialization
double input = 0.0;
do {
//loop body
cout << "Enter a positive number: ";
cin >> input;
if (input < 0.0) {
cout << "You must enter a positive number!\n";
}
} while (input < 0.0); //loop condition
cout << "You entered: " << input << endl;
return 0;
}
|
When to Use do-while Statements
- Sometimes used in professional programming
- You can accomplish the same control flow with a
while loop
- You can use it whenever you want to force a minimum of one iteration
^ top
6.1.4: for Statements
- Provides a more compact loop
- Syntax:
for (initializer; condition; increment) {
//loop body
...
}
Initialization, loop-test, and increment-expression are part of the syntax
initializer expression: defines the initial value used to control the loop
condition expression: determines when the loop will end
increment expression: evaluated at the end of each loop iteration
Statements to repeat are enclosed in curly brackets
Execution sequence as follows:
- When
for statement reached -- initialization executes
- Check if condition is
true
- if
true then continue with Step 3
- Otherwise, continue with Step 6
- Execute block containing the loop body
- When end of loop body is reached, execute the increment
- Return to Step 2
- Loop is finished: continue with statements after the loop
Counter-Controlled-Loop Example
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
using namespace std;
int main() {
int count;
for (count = 0; count < 5; count++) {
cout << count << endl;
}
return 0;
}
|
- Note that code is indented in the loop body for readability
Counting Down
- Can also count downwards
- Positive numbers step higher (+inf) and negative numbers step lower (-inf)
- What is displayed with the following?
#include <iostream>
using namespace std;
int main() {
int count;
for (count = 5; count > 0 ; count--) {
cout << count << endl;
}
return 0;
}
When to Use for Statements
- Very often used in professional programming
- Especially useful for counter-controlled loops
^ top
6.1.5: break and continue Statements
break and continue statements transfer control to another part of a program
- Within a loop
break statements an immediate exit
- Transfers control to the statement following the loop
- Provides a way to break out of an intentional infinite loop
#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;
}
continue statement transfers control to the loop test
Causes the loop to skip the rest of the current iteration
When executed within a loop, starts the next iteration of the loop immediately
When to Use break and continue Statements
- Use
break statements in switch statements only
- Never use
break in looping constructs
- Poor coding habit
- Should only have one exit point in a loop
- In this course, you will never need to write infinite loops
- You do not need to use
continue statements either
- You can accomplish the same operation other ways
^ top
6.1.6: Summary
- C++ provides many control statements
- They provide alternatives to the basic statements covered earlier
- Of those covered today, the most useful is the
for loop
- Provides a compact looping structure often used for counter-controlled repetition
- Incudes three of the loop requirements in the syntax of the loop
Check Yourself
- What is the difference between a
while and a do-while loop?
- What are the advantages of using a
for loop compared to other looping statements?
^ top
Exercise 6.1
- Start a text file named exercise6.txt.
- Prepare the exercise header as described in the HowTo on submitting exercises
- Label this exercise: Exercise 6.1
- Complete the following and record the answers to any questions in exercise6.txt.
Specifications
- Save the following code as
for5.cpp
- Convert the code to use a
for loop rather than a while loop.
- Turn in the modified code along with your
exercise6.txt file
- Record answers to the following questions in
exercise6.txt.
Q1: What is the chief advantage of using a for loop?
Q2: The for loop seems most appropriate for which type of looping pattern?
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <iostream>
using namespace std;
int main() {
int count = 1; // initialization code
while (count < 6) { //loop termination condition
//loop body
cout << count << endl;
count = count + 1; // adjust the counter
}
return 0;
}
|
^ top
6.2: Overloading Function Names
Objectives
At the end of the lesson the student will be able to:
- Code overloaded functions
- Describe how C++ resolves function calls
- Describe when to overload functions
|
^ top
6.2.1: About Overloading
- You can have several functions with the same name in a program
- Need different parameter set (i.e. signature) for each function
- Number of parameters
- Parameter types
- Order of parameters
- Return type is not part of the signature
- Cannot be used to distinguish between two functions with the same name and signature
For Example
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;
// Function prototypes
double square(double x);
int square(int x);
int main() {
cout << square(5) << endl;
cout << square(6.5) << endl;
}
int square(int x) {
cout << "Using type int: ";
return x * x;
}
double square(double x) {
cout << "Using type double: ";
return x * x;
}
|
- First call to
square uses function with int signature
- Second call uses function with double signature
Using type double: 42.25
Using type int: 25
^ top
6.2.2: Overloading Resolution
- Function call resolution:
- Looks for exact signature
- Looks for 'compatible' signature
- First: looks for exact signature
- Because no argument conversion required
- Second: looks for 'compatible' signature
- First where promotion is possible, with no loss of data
int => double
Second with demotion, with a possible loss of data
double => int
For Example
- Given following functions:
void f(int n, double m) {}
void f(double n, int m) {}
void f(int n, int m) {}
- Making these calls:
f(98, 99); => Calls 3
f(5.3, 4); => Calls 2
f(4.3, 5.2); => ??
- Avoid such confusing overloading
^ top
6.2.3: Automatic Type Conversion and Overloading
- Typically you should make numeric formal parameters of type
double
- Allows for any numeric type
- Any narrower data type can safely be promoted to wider types
- Avoids overloading because of different numeric types
For Example
double mpg(double miles, double gallons) {
return (miles / gallons);
}
Example function calls:
mpgComputed = mpg(5, 20);
- Converts
5 and 20 to doubles, then passes them to the function
mpgComputed = mpg(5.8, 20.2);
mpgComputed = mpg(5, 2.4);
- Converts
5 to 5.0, then passes the values to the function
^ top
6.2.4: Summary
- A programmer can declare many functions using the same name
- However, the parameter list must be different between each function
- Useful when you want to have the same function operate on different data types
- However, you can avoid overloading for numbers by relying on automatic type conversion
- C++ automatically changes values to the needed type
- By making your numeric types
double, you can use promotion instead of overloading
Check Yourself
- How many functions can you define for each program?
- If two functions have the same name, what must be different in each declaration and definition?
- How does C++ resolve overloaded functions?
- When should you overload functions?
^ top
Exercise 6.2
- Label this exercise: Exercise 6.2
- Complete the following and record the answers to any questions in exercise6.txt.
Specifications
- Suppose you have two functions:
double score(double time, double distance) {}
double score(double points) {}
Which function would be used in the following function call?
double finalScore = score(95.7);
- Suppose you have two functions:
double answer(double data1, double data2) {}
double answer(double time, int count) {}
Which function would be used in the following function call?
double y = 5.0;
double x = answer(y, 6.0);
^ top
6.3: void Functions and Tracing Calls
Objectives
At the end of the lesson the student will be able to:
- Describe how
void functions differ from functions that return a value
- Declare and define
void functions
- Decide when to use
void functions
- Trace function calls
|
^ top
6.3.1: void Functions
- Previously we looked at functions that returned one value
- Functions returning a value use the
return statement
return result;
A function that returns no value is called a void function
In C++, void functions are defined like functions that return a value
However, the keyword void replaces the return type
For example, what do you notice that is different about the following?
void showResults(double fDegrees, double cDegrees) {
cout << fDegrees
<< " degrees Fahrenheit is equivalent to "
<< cDegrees << " degrees Celsius." << endl;
return;
}
There are only two differences between definitions for void functions and other functions.
void return type
return statement is optional and does not specify a value if used
If no return type is specified, the function returns after executing the last statement
Why might you code a return statement if its use is optional?
Here is an example program using the void function shown above
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <iostream>
using namespace std;
// Displays the results of a ddegree conversion
void showResults(double fDegrees, double cDegrees);
int main() {
double fTemperature, cTemperature;
cout << "Enter a temperature in Fahrenheit: ";
cin >> fTemperature;
cTemperature = 5.0 / 9 * (fTemperature - 32);
showResults(fTemperature, cTemperature);
return 0;
}
void showResults(double fDegrees, double cDegrees) {
cout << fDegrees
<< " degrees Fahrenheit is equivalent to "
<< cDegrees << " degrees Celsius." << endl;
return;
}
|
^ top
6.3.2: Calling void Functions
- When you call a
void function you must code the call as a separate statement
- A
void function cannot be part of an expression
- For example, look at the following function call:
showResults(32.5, 0.3);
This will cause the following to appear on the screen:
32.5 degrees Fahrenheit is equivalent to
0.3 degrees Celsius.
Note that the void function call does not return a value
If the function call was part of an expression like the following, what would be printed?
cout << showResults(32.5, 0.3); // not allowed
If you tried to compile code like this, you would get a lengthy set of error messages
^ top
6.3.3: Functions Calling Functions
- Functions may call other functions
- Within the body of the function, you can code a function call
- We are already doing this when
main() calls another function
- What does the following program display to the console?
Example of Functions Calling Functions
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
|
#include <iostream>
#include <iomanip>
using namespace std;
// Returns the square of a number
double square(double number);
// Displays a message to the console
void out(string funName, double value);
int main() {
double number = 5;
out("main", number);
double result = square(5);
out("main", result);
return 0;
}
double square(double number) {
out("square", number);
double result = number * number;
out("square", result);
return result;
}
void out(string funName, double value) {
cout << "In " << funName << "() the value is "
<< value << endl;
}
|
^ top
6.3.4: Tracing a Function Call
- When functions call functions, you need to follow the flow of execution
- A function call transfers control to the first statement of the called function
- When a return point is reached, control passes back to the point right after the function call
- If the function call is part of an expression, the returned value is used in the expression
- Let's trace the flow in the following code by line number:
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
|
#include <iostream>
#include <iomanip>
using namespace std;
// Returns the square of a number
double square(double number);
// Displays a message to the console
void out(string funName, double value);
int main() {
double number = 5;
out("main", number);
double result = square(5);
out("main", result);
return 0;
}
double square(double number) {
out("square", number);
double result = number * number;
out("square", result);
return result;
}
void out(string funName, double value) {
cout << "In " << funName << "() the value is "
<< value << endl;
}
|
^ top
6.3.5: Summary
- You code a
void return type when you do not want a function to return a value
- For example:
void showResults(double fDegrees, double cDegrees) {
cout << fDegrees
<< " degrees Fahrenheit is equivalent to "
<< cDegrees << " degrees Celsius." << endl;
return;
}
The return statement is optional for void functions
When a void function executes the last statement, it automatically returns
If a return statement is coded for a void function, it does not include a return value
return;
Functions with a void return type cannot be called as part of an expression
showResults(32.5, 0.3);
NOT:
cout << showResults(32.5, 0.3);
Functions can call other functions, just like main() calls other functions
Check Yourself
- How do
void functions differ from functions that return a value?
- How do you declare and define a void function?
- When do you use a
void function?
- Are you required to have a return statement in a
void function definition?
- What effect would removing the return statement from the following function have on compiling or executing the program?
void showResults(double fDegrees, double cDegrees) {
cout << fDegrees
<< " degrees Fahrenheit is equivalent to "
<< cDegrees << " degrees Celsius." << endl;
return;
}
- Assuming that
showResults() is a void function, what is wrong with:
cout << showResults(32.5, 0.3); // not allowed
- How do you code a function to call another function?
^ top
Exercise 6.3
Specifications
- Label this exercise: Exercise 6.3
- In
exercise6.txt, list the line numbers of the following program in the order they are processed.
- Do not bother to list lines containing just a closing curly brace (
}) of a function definition.
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
|
#include <iostream>
#include <iomanip>
using namespace std;
// Returns the square of a number
double square(double number);
// Displays a message to the console
void out(string funName, double value);
int main() {
double number = 5;
out("main", number);
double result = square(5);
out("main", result);
return 0;
}
double square(double number) {
out("square", number);
double result = number * number;
out("square", result);
return result;
}
void out(string funName, double value) {
cout << "In " << funName << "() the value is "
<< value << endl;
}
|
^ top
6.4: Call-By-Reference Parameters
Objectives
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
6.4.1: About Parameter Passing
- Two ways to pass arguments to parameters
- Call-by-value
- A copy of the value is passed
- Call-by-reference
- The address of the actual argument is passed
- All our functions so far have used call-by-value parameters
Call-by-Value Parameters
- A copy of the actual argument is passed
- Same as a local variable with special initialization inside the function
- If modified, only the local copy changes
- The function has no access to the actual argument from the caller
- This is the default operation for function calls
- Used in all our examples so far
Example of Call-ByValue Parameters
- What does this program output?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <iostream>
using namespace std;
int mystery(int param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
num = mystery(num);
cout << "Later, num=" << num << endl;
return 0;
}
int mystery(int param) {
cout << "param=" << param << endl;
param = param * 2;
return param;
}
|
^ top
6.4.2: Call-By-Reference Parameters
- C++ has another parameter-passing mechanism known as call-by-reference
- Used to provide access to caller's actual argument inside a function
- Caller's data can be modified by the called function!
- Specified by an ampersand '
&' after the type in the parameter list
For Example
- Here is a program that outputs the same things as the previous example
- What is different?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <iostream>
using namespace std;
void mystery(int& param);
int main() {
int num = 2;
cout << "At first, num=" << num << endl;
mystery(num);
cout << "Later, num=" << num << endl;
return 0;
}
void mystery(int& param) {
cout << "param=" << param << endl;
param = param * 2;
}
|
Call-By-Reference Details
- What's really passed in?
- A reference back to the caller's original argument!
- Refers to memory location of the original argument
- Called an address, which is a unique number referring to a place in memory
- Note that arguments for call-by-reference parameters must be variables, not constants
^ top
6.4.3: Mixed Parameter Lists
- You can combine parameter-passing mechanisms
- Parameter lists can include pass-by-value and pass-by-reference parameters
- As usual, the order of arguments in the list is critical:
void mixedCall(int& par1, int par2, double& par3);
Function call:
int arg1 = 0, arg2 = 1;
double arg3 = 2.2;
mixedCall(arg1, arg2, arg3);
arg1 must be integer type and is passed by reference
arg2 must be integer type and is passed by value
arg3 must be double type and is passed by reference
^ top
6.4.4: Summary
- A formal parameter is a local variable with special initialization
- The parameter is filled in with the actual argument during the function call
- Call-by-value parameters are local copies of argument in the function body
- The actual argument cannot be modified
- Call-by-reference parameters allow you to change the variable used in the function call
- Actual argument can be modified
'&' symbol (ampersand) identifies call-by-reference variables
- Call-by-reference passes the memory address of actual argument
- Whatever is done to a formal parameter in the function body, is actually done to the value at the memory location of the argument variable
- Makes the parameter an alias for the original argument
- Arguments for call-by-reference parameters must be variables, not constants
- You can mix call-by-value and call-by-reference parameters in a function
void mixedCall(int& par1, int par2, double& par3);
Check Yourself
- What happens in a call when the function is defined for call by value?
- What happens in a call when the function is defined for call by reference?
- How do call-by-value and call-by reference differ?
^ top
Exercise 6.4
- Label this exercise: Exercise 6.4
- Complete the following and record the answers to the questions in exercise6.txt.
Specifications
Consider the following program:
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;
void swapValues(int& variable1, int& variable2);
int main() {
int num1 = 1, num2 = 2;
cout << "Original values: " << num1
<< " " << num2 << endl;
swapValues(num1, num2);
cout << "Swapped values: " << num1
<< " " << num2 << endl;
return 0;
}
void swapValues(int& variable1, int& variable2) {
int temp = variable1;
variable1 = variable2;
variable2 = temp;
}
|
Q1: What does the program do?
Q2: What output do you get if you remove the ampersands '&' from the swapValues() parameter list?
Q3: How do call-by-value and call-by reference differ?
^ top
Wrap Up
^ top
Home
| WebCT
| Announcements
| Day Schedule
| Eve Schedule
Course info
| Help
| FAQ's
| HowTo's
| Links
Last Updated: October 27 2005 @16:24:00
|