Chapter 7-8

advertisement
Functions
1
Example: Power, Square Root and Absolute values of a number
#include <cmath>
…
float num;
float power, squareRoot, absolute;
cout << "Please input a float number: ";
cin >> num;
power = pow ( num , 2 );
cout << "The power is " << power << endl;
if ( num > 0 )
{
squareRoot = sqrt ( num );
cout << "The square root is " << squareRoot << endl;
}
else
cout << num << " is negative. No squre root!" << endl;
absolute = fabs ( num );
cout << "The absolute value is " << absolute << endl;
2
Math Functions in <cmath>
 Need to use #include <cmath> or #include <math.h>
float pow ( float base, float exponent );
float sqrt ( float num );
float fabs ( float num );
 They are functions!
 These are function prototypes!
3
What other functions have you learned?
 bool cin.eof();
 int string.length();
 string string.substr();
 smanip setprecision(int n);
 smanip setw(int n);
How to define and use your own function?
4
Example: MAX of 2 numbers
#include <iostream>
using namespace std;
int Max ( int num1, int num2 );
int main()
{
int num1, num2, maxResult;
cin >> num1 >> num2;
// function prototype
(function declaration)
// function
maxResult = Max ( num1, num2 );
cout << "The max is " << maxResult << endl;
call
return 0;
}
int Max ( int num1, int num2 )
{
int result;
if ( num1 > num2 )
result = num1;
else
result = num2;
// function heading
function definition
return result;
}
5
Review: Element of a function
Return Data Type
Function Body
Function Name
Parameter List
int Max ( int num1, int num2 )
{
int result;
if ( num1 > num2 )
result = num1;
else
result = num2;
return result;
}
6
Function Prototype
 C++ programmer usually place all supporting functions
after the main function.
 C++ rule: identifiers must be declared before use!
 Place a function prototype before the main function as a
declaration.
 Two ways to declare a function:
int max ( int num1, int num2 );
OR
int max ( int, int );
Add a semicolon to the function heading, and you get the function prototype!
7
Function Prototype
Common Practice!
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
int max ( int num1, int num2 );
int max ( int num1, int num2 )
{
int result;
if ( num1 > num2 )
result = num1;
else
result = num2;
int main()
{
…
maxResult = max ( num1, num2 )
…
}
int max ( int num1, int num2 )
{
int result;
if ( num1 > num2 )
result = num1;
else
result = num2;
return result;
=
return result;
}
int main()
{
…
maxResult = max ( num1, num2 )
…
}
}
8
Review: Two Types of Functions
 Void Function
 Return data type is void
 Don’t need a return statement in the function
 Function call format: functionName(parameters);
 Value-Return Function
 Return data type is some real data type (int, float, string)
 Need a return statement to return a value to the caller
function
 Function call format: var = functionName(parameters);
OR use functionName(parameters)as a variable.
9
Formal parameters vs. Actual parameters (Arguments)
 Formal parameters appears in a function heading.
int max ( int num1, int num2 );
Used in the callee function.
 Actually parameters (Arguments) appear in a function call.
result = max ( 2, 3 );
 During a function call, an argument can be a literal, variable, or
expression.
result = pow( 3, 2 );
result = fabs ( num );
result = sqrt ( num / 2 + 1 );
 A function is not required to have arguments.
eof();
Used in the caller function.
10
Void Function
#include <iostream>
#include <string>
using namespace std;
const int HEIGHT = 10;
void PrintLine(int height);
int main()
{
int height = HEIGHT;
while ( height > 0 )
{
PrintLine(height);
height --;
}
return 0;
}
Formal parameter: height
Actual parameter: height
 They can have the same name!
void PrintLine(int height)
{
string spaceLine = "";
string dollarLine = "";
int count = 0;
while ( count < height - 1 )
{
spaceLine += " ";
count ++;
}
count = 0;
while ( count < 2 * ( HEIGHT - height )
+ 1 )
{
dollarLine += "$";
count ++;
}
cout << spaceLine << dollarLine
<< endl;
}
11
Value-Return Function
Formal parameter: payRate, hour
Actual parameter: rate, hour
 They can have different names!
#include <iostream>
using namespace std;
float grossPay(float payRate, float hour);
int main()
{
float hours;
float rate;
float salary;
cout << "Please enter your pay rate “
<< “(per hour): ";
cin >> rate;
cout << "Please enter your working “
<< “hours: ";
cin >> hours;
salary = GrossPay(rate, hours);
cout << "Your salary is " << salary
<< “.” << endl;
float GrossPay(float payRate, float hour)
{
float salary;
if (hour <= 40)
salary = hour * payRate;
else
{
salary = ( hour - 40 ) * payRate *
1.5 + 40 * payRate;
cout << endl << "You have "
<< ( hour - 40 )
<< " hours overtime." << endl;
}
return salary;
}
return 0;
}
12
Function Names
 Meaningful names
 Names for functions and methods with a return type of void
should generally be verb phrases such as ComputePay() and
PrintOrders().
 Names for functions and methods with other return types
should generally be nouns or noun phrases such as
Average() and MonthlySalary().
 Capitalize the first letter of each word!
 Formal and actual parameters can have the same name
 They are different variables in different scopes
 Normally they have different names
13
Activation Record
 There is one activation record for each function call.
 An activation record contains:
 Local variables of the function called
 Return address
 Parameters for the function called
Locals
Return Address
Parameters
Activation Record for GrossPay
int main()
{
float hours;
float rate, salary;
cout << "Please enter your pay rate “
<< “(per hour): ";
cin >> rate;
cout << "Please enter your working “
<< “hours: ";
cin >> hours;
salary = GrossPay(rate, hours);
cout << "Your salary is " << salary
<< “.” << endl;
return 0;
}
hours
rate
Input values:
?
?
salary ?
45
10
475
float GrossPay(float payRate, float hour)
{
float salary;
if (hour <= 40)
salary = hour * payRate;
else
{
salary = ( hour - 40 ) * payRate *
1.5 + 40 * payRate;
cout << endl << "You have "
<< ( hour - 40 )
<< " hours overtime." << endl;
}
return salary;
}
10
45
payRate
10
hour
45
salary
?
475
Scope of Variables
 The region of code where it is legal to reference (use)
an identifier.
 Local Scope
 Global Scope
 Class Scope (Later in this semester.)
16
Statement Block
 Between a pair of matching braces
 e.g. The body of a function
int main()
{
int alpha = 10;
// A block for if statement
if (alpha > 3)
{
int num;
cin >> num;
alpha += num;
}
return 0;
}
17
Local Scope
int main()
{
int alpha = 10;
 The scope of an
// A code block
if (alpha > 3)
{
int num;
cin >> num;
alpha += num;
}
cout << "num = “ << num;
// Run time error!
return 0;
identifier declared
inside a block extends
from the point of
declaration to the end
of that block.
}
18
Nested Local Scope
 local identifiers have name precedence!
 The scope of an identifier does not include any nested block
that contains locally declared identifier of the same name!
int main ()
{
int num = 0;
string name = “Kyle”;
while ( num < 5 )
{
string name = “Alice”;
cout << name << num << endl;
num ++;
}
cout << endl << name;
return 0;
}
What is the output?
Alice0
Alice1
Alice2
Alice3
Alice4
Kyle
19
Global Scope
 The scope of an identifier declared outside all
functions (and classes) extends from the point of
declaration to the end of the entire source file.
Programming Rules:
No global variables!
20
Scope of a Function Name
 A function name has global scope.
 Function definitions cannot be nested within function
definitions!
int main ()
{
int num = 0;
string name = “Kyle”;
while ( num < 5 )
{
void PrintAlice ( int count )
{
string name = “Alice”;
cout << name << count << endl;
}
num ++;
}
cout << endl << name;
return 0;
}
// Can we do that?
// NO!
21
Scope of Function Parameters
 Formal parameters

Local scope

Same as local variable

Cannot reference it outside the function

Receive values on function call
 Actual parameters (no global variables)

Local scope

Cannot reference it inside the called function
22
Example: GrossPay
#include <iostream>
using namespace std;
formal parameters
float GrossPay(float payRate, float hour);
int main()
{
int hour;
float rate;
float salary;
scope
cout << "Please enter your pay rate “
<< “(per hour): ";
cin >> rate;
cout << "Please enter your working “
<< “hours: ";
cin >> hour;
actual parameters
salary = GrossPay(rate, hour);
cout << "Your salary is " << salary
<< “.” << endl;
float GrossPay(float payRate, float hour)
{
float salary;
if (hour <= 40)
salary = hour * payRate;
else
{
salary = ( hour - 40 ) * payRate *
1.5 + 40 * payRate;
cout << endl << "You have "
<< ( hour - 40 )
<< " hours overtime." << endl;
}
return salary;
}
scope
return 0;
}
23
Example: Using a flag
float DoIt(int num, char op);
int main()
{
int base;
float result;
char choice;
cout << “Enter a number: ”;
cin >> base;
cout << “C for Cube and S for Square Root: ”;
cin >> choice;
// ---------------------------// Precondition: op is ‘C’ or ‘S’
// Postcondition: the cube of
// num is computed when op is
// ‘C’, and square root of num
// is computed when op is ‘S’.
// parameters: in, in
// -----------------------------float DoIt(int num, char op)
{
if (op == ‘C’)
result = pow(num, 3);
else
result = sqrt(num);
while (choice != ‘C’ && choice != ‘S’)
{
cout << “C for Cube and S for Square Root: ”;
cin >> choice;
}
result = DoIt(base, choice);
return result;
}
cout << “The result: ” << result;
return 0;
}
// What is wrong?
// Result not declared in the
// function!
24
Example: Using a flag
int DoIt(int num, char op);
int main()
{
int base;
float result;
char choice;
cout << “Enter a number: ”;
cin >> base;
cout << “C for Cube and S for Square: ”;
cin >> choice;
while (choice != ‘C’ && choice != ‘S’)
{
cout << “C for Cube and S for Square: ”;
cin >> choice;
}
result = DoIt(base, choice);
cout << “The result: ” << result;
return 0;
}
// -----------------------------// Precondition: op is ‘C’ or ‘S’
// Postcondition: the cube of
// num is computed when op is
// ‘C’, and square root of num
// is computed when op is ‘S’.
// parameters: in, in
// -----------------------------float DoIt(int num, char op)
{
float result;
if (op == ‘C’)
result = pow(num, 3);
else
result = sqrt(num);
return result;
}
// The two variables
// result have the same
// name, but different!
25
Programming Ground Rules
 All functions, including the main function, should be no more than 30
lines long, from the left brace to the right brace, inclusive.
 Every function and method, except the main function, must have a
comment which describes
 what it does and
 whether the parameters are input, output, or input and output.
 Be sure to document the purpose of any parameter which isn't obvious
from its name alone.
 Thus function and method headers must have the following format:
//--------------------------------------------------------// A few lines describing what the function or method does.
// params: (in/out/inout, ...)
//--------------------------------------------------------result_type function_name(type1 param1, type2 param2, ...)
26
Function Parameters
 IN parameters:
 The value of the actual parameter is passed into the
function and assigned to the formal parameter.
 OUT parameters:
 The value of formal parameter is passed out of the
function and assigned to the actual parameter.
 InOut

Both In and Out.
27
Example: IN Parameter
#include <iostream>
using namespace std;
float GrossPay(float payRate, float hour);
int main()
{
int hour;
float rate;
float salary;
cout << "Please enter your pay rate “
<< “(per hour): ";
cin >> rate;
cout << "Please enter your working “
<< “hours: ";
cin >> hour;
salary = GrossPay(rate, hour);
cout << "Your salary is " << salary
<< “.” << endl;
The value of rate and hour
in the main function
is passed to payRate and hour
in the grossPay function.
Can we write a function
to input rate and hour?
How to pass the values back to
the main function?
return 0;
}
28
Example: OUT Parameter
float GrossPay(float payRate, float hour);
void GetInput(float& payRate, float& hoursWorked);
int main()
{
float hour, rate, gross;
// Call function getInput() to get two values
GetInput(rate, hour);
// Call function grossPay to get one value
gross = GrossPay(rate, hour);
// display result
cout << "Your salary is " << gross << endl;
return 0;
}
29
Function definition of GetInput
//
//
//
//
//
------------------------------------------------The function inputs payRate and hoursWorked and
pass both values back to the calling function.
Parameters: (out, out)
-------------------------------------------------
void GetInput(float& payRate, float& hoursWorked)
{
cout << "Enter pay rate: ";
cin >> payRate;
cout << "Enter hours: ";
cin >> hoursWorked;
}
//
//
//
//
return; // in void functions, using return is optional.
The function does input with prompt, but OUT parameters!
How can it pass two values back?
Out Parameters: &
Statement return can pass only one value back!
30
Function definition of GrossPay
// ------------------------------------------------// The function computes and returns the gross pay
//
based on the pay rate and hours. Hours over
//
40 will be paid 1.5 times the regular pay rate.
// Parameters: (in, in)
// ------------------------------------------------float GrossPay(float payRate, float hour)
{
if (hour > REG_HOURS)
payRate = (hour - REG_HOURS) * OVER_TIME * payRate +
REG_HOURS * payRate;
else
payRate = hour * payRate;
return payRate;
}
// No local variable
// payRate is used to store the result
31
Reference and Value Parameters
float GrossPay(float payRate, float hour);
void GetInput(float& payRate, float& hoursWorked);
 Value parameter: No & DataType identifier, …
The value of actual parameter is passed to the formal parameter
 Reference Parameter: With & DataType& identifier, …
The address of actual parameter is passed to the formal parameter
 Does the actual parameter change its value when the corresponding
formal parameter changes its value?
 Value parameter (no &): NO
 Reference parameter (&): YES
32
Reference and Value Parameters
 Function call using value parameters:
gross = GrossPay(rate, hour); float
main
Memory
rate
22.5
hour
50
GrossPay(float payRate, float hour);
GrossPay
payRate
22.5
hour
50
 Function call using reference parameters:
GetInput(rate, hour);
Memory
7000 main
rate
22.5
7004
50
hour
void GetInput(float& payRate, float& hoursWorked);
GetInput
70
&payRate
00
70
&hoursWorked
04
33
Trace Functions with OUT parameters
Input: 10
45
GetInput(rate, hour);
// Reference parameters
gross = GrossPay(rate, hour);// Value parameters
main()
rate
?
hour
?
?
gross
GetInput()
10
45
450
GrossPay()
payRate
&rate
payRate
10
hoursWorked
&hour
hour
45
salary
?
450
34
Example: InOut Parameter
int main()
{
float score, highest, lowest;
int scoreCount = 0;
cin >> score;
while (!cin.eof())
{
if (scoreCount == 0)
{
highest = score;
lowest = score;
}
else
{
if (score > highest)
highest = score;
if (score < lowest)
lowest = score;
}
scoreCount ++;
cin >> score;
}
cout << “Highest: “ << highest << “\nLowest: “ << lowest;
return 0;
}
// Task: Use a function to update highest and lowest.
35
Example: InOut Parameter
void UpdateMaxMin ( float, float&, float& );
int main()
{
float score, highest, lowest;
int scoreCount = 0;
cin >> score;
while (!cin.eof())
{
if (scoreCount == 0)
{
highest = score;
lowest = score;
}
else
UpdateMaxMin ( score, highest, lowest );
scoreCount ++;
//
//
//
//
//
//
-------------------------------The function uses the value of
num to update the
values of max and min.
Parameters: ( In, InOut, InOut )
--------------------------------
void UpdateMaxMin( float num,
float& max,
float& min )
{
if (num > max)
max = num;
}
if (num < min)
min = num;
cin >> score;
}
cout << "Highest: " << highest
<< "\nLowest: " << lowest;
return 0;
}
36
Example: InOut Parameter
 Function call:
UpdateMaxMin ( score, highest, lowest );
 Function Definition:
void UpdateMaxMin( float num, float& max, float& min )
main
Memory
updateMaxMin
score
20
num
highest
20
10
max
&highest
lowest
2
min
&lowest
37
Trace Functions with InOut parameters
Input: 45
40
50
updateMaxMin ( score, highest, lowest );
//Function call
void updateMaxMin( float num, float& max, float& min ) //Function definition
38
Value Parameter and Reference Parameter
 What can the actual parameter be for a value parameter?
A VALUE!
Literal value
Variable
Expression
(magic number)
(initialized!)
(with all variables initialized)
 What can the actual parameter be for a reference parameter?
AN ADDRESS!
Literal value:
Expression:
Variable:
NO
NO
YES
initialized or uninitialized
39
Actual Parameter
 Does the actual parameter change its value when
the corresponding formal parameter changes its
value?
Value Parameter
NO!
Reference Parameter
YES!
40
Function Calls
 Main function can call another function A
 A function can also call another function B
main
A
B
Caller
Callee
Caller
Callee
41
Decompose the program by functions
 Modularity
 Any function or method (including the main function) can
have at most 30 lines.
 A function should implement ONE basic functionality.

Functions and methods which focus on computation should not
produce output using cout statements.
 Check:
 Can I replace the loop body with a function?
 Can I use a function to get valid input?
 Can I use a function to do some particular computation?
 Is there any activity that is repeated multiple times in the
program?
42
Design Function Interface
 What parameters should be passed?
 How? In, Out, or InOut?
 In: pass by value. Recommended!
 Out: pass by reference.
 InOut: pass by reference.
If possible, try to avoid passing reference parameters!
Because it might cause unexpected values changes of the
caller’s variables.
43
Example: Bad Functions
float GetRate(float rate)
{
cout << “Enter the rate: ”;
cin >> rate;
return rate;
}
// Bad: Why use parameter?
float GetRate()
{
float rate;
cout << “Enter the rate: ”;
cin >> rate;
return rate;
}
// Good: Use local variable!
float GrossPay(float rate, float hour)
{
float pay = rate * hour;
cout << “The pay is “ << pay;
return pay;
}
// Bad: No output in calculation
functions!
void Power ( int& base, int& exponent,
int& result )
{
result = 1;
while ( exponent > 0 )
{
result = result * base;
exponent --;
}
}
// Bad: No need to use reference
parameter!
44
Example: Print a chess board
Pseudo Code:
while height is not 8 yet
if line# is odd, then print an odd row
otherwise, print an even row
Print an odd row:
while cell height is not enough
while cell width is not enough
if cell# is odd
print N spaces
otherwise, print N ‘@’
Do we need two print row functions?
Use a flag to indicate odd or even row!
Print an even row:
while cell height is not enough
while cell width is not enough
if cell# is odd
print N ‘@’
otherwise, print N spaces
45
Example: Print a chess board
Pseudo Code:
while height is not 8 yet
if row# is odd, then print an odd row
otherwise, print an even row
The function printRow is too long!
Print a row:
while cell height is not enough
while cell width is not enough
if cell# is odd
print N spaces if row# is even, or
print N ‘@’ if row# is odd
otherwise,
print N ‘@’ if row# is even, or
print N spaces if row# is odd
replace the circled code with function printLine!
Further pass the flag to printLine.
46
Example: Print a chess board
const
const
const
const
const
int BOARD_WIDTH = 8;
int CELL_WIDTH = 10;
int CELL_HEIGHT = 4;
char FILL = '@';
char EMPTY = ' ';
int main()
{
int count = 0;
while ( count < BOARD_WIDTH )
{
printRow ( count );
count ++;
}
return 0;
}
void printRow ( int rowNum )
{
int countHeight = 0;
while ( countHeight < CELL_HEIGHT )
{
printLine ( rowNum );
countHeight ++;
}
}
void printLine ( int rowNum)
{
int countWidth = 0;
int countCell = 0;
while ( countWidth < BOARD_WIDTH )
{
countCell = 0;
if ( countWidth % 2 == 0 )
while ( countCell < CELL_WIDTH )
{
if ( rowNum % 2 == 0)
cout << EMPTY;
else
cout << FILL;
countCell ++;
}
else
while ( countCell < CELL_WIDTH )
{
if ( rowNum % 2 == 0)
cout << FILL;
else
cout << EMPTY;
countCell ++;
}
Can it be further
countWidth ++;
decomposed?
}
cout << endl;
47
}
Summary










Function definition
Function prototype
Void functions vs. value-return functions
Formal parameters vs. actual parameters
Scope of variables
Scope of function parameters
Scope of function names
Parameter passing: In, Out and InOut
Value parameters vs. reference parameters
Program decomposition
48
More about getting input
 cin.get()
 cin.ignore()
 getline(cin, string)
49
cin.get(char&)
 the >> operator skips any leading whitespace or new
line in the input stream.
 What if we want to read the whitespace?
char ch1, ch2, ch3;
//Input: a b c
cin >> ch1 >> ch2 >> ch3;
//OR
cin.get(ch1);
cin.get(ch2);
cin.get(ch3);
//ch1 = ‘a’, ch2 = ‘b’, ch3=‘c’
//ch1 = ‘a’, ch2 = ‘ ’, ch3=‘c’
50
cin.ignore()
 cin.ignore(200, ‘\n’):
 skip the next 200 input characters OR
 skip characters until a newline character is read
 whichever comes first!
string str;
cin.ignore(20, '\n');
cin >> str;
cout << endl << str;
If the input is “This is a test to see which string will be input.”,
what do you think is the input?
51
getline(cin, string)
 How to read a complete line of input?
 getline(cin, string) will read everything until it reaches
a newline character.
52
Download