3.2 Predefined Functions 3.1 Top Down Design

advertisement
3.2 Predefined Functions
3.1 Top Down Design
?
?
Libraries
Step wise refinement, also known as divide
and conquer, means dividing the problem
into subproblems such that once each has
been solved, the big problem is solved.
The subproblems should be smaller and
easier to understand and to solve than the
big problem.
?
?
?
C++ comes with libraries of predefined
functions.
How do we use predefined (or library)
functions?
Everything must be declared before it is used.
The statement #include <file> brings the
declarations of library functions into your
program, so you can use the library functions.
1
2
3.2 Predefined Functions
3.2 Function call
Libraries
#include <cmath>
#include <iostream>
// include declarations of math
// library functions
// include definitions of
// iostream objects
// make names available
using namespace std;
int main()
{
cout << sqrt(3.0) << endl; // call math library function
}
// sqrt with argument 3.0, send
// the returned value to cout 3
Display 3.1 A Function call
?
?
?
A function call is an expression consisting of a function
name followed by arguments enclosed in parentheses.
Multiple arguments are separated by commas.
Syntax:
FunctionName(Arg_List)
where Arg_List is a comma separated list of arguments.
Examples:
?
?
4
Display 3.1 A Function call (b)
//Computes the size of a dog house that can be purchased
//given the user’s budget.
#include <iostream>
#include <cmath>
using namespace std;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << "For a price of $" << budget << endl
<< "I can build you a luxurious square dog house\n"
<< "that is " << length_side
<< " feet on each side.\n";
int main( )
{
const double COST_PER_SQ_FT = 10.50;
double budget, area, length_side;
return 0;
cout << "Enter the amount budgeted for your dog house $";
cin >> budget;
area = budget/COST_PER_SQ_FT;
length_side = sqrt(area);
// the function call
side = sqrt(area);
cout <<“2.5 to the power 3.0 is “
<< pow(2.5, 3.0);
5
}
6
3.2 Predefined Functions
PITFALL: Problems with Library functions
?
?
?
?
Type changing functions
Some compilers do not comply with the ISO
Standard.
If your compiler does not work with
#include <iostream>
use
#include <iostream.h>
Similarly, for headers like cstdlib: use stdlib.h,
and for cmath, use math.h
Most compilers at least coexist with the headers
without the .h, but some are hostile to these
headers.
Question: 9/2 is an int, but we want the 4.5 floating point
result. We want the integer part of some floating
point number. How do we manage?
Answer: Type casting, or “type changing functions”.
C++ provides a function named double that takes a
value of some other type and converts it to double.
Example:
int total, number;
double ratio;
// input total, number
winnings = double(total) / number;
7
8
PITFALL: Integer division drops the
fractional part
?
3.3 Programmer Defined Functions
function definitions
REMEMBER: integer division returns just the
quotient. The remainder (and any fractional part) are
dropped.
?
?
?
?
If the numerator and denominator are both integer
values, the division is done as integer arithmetic,
dropping the fractional part.
You can define your own functions.
You can put your functions in the same file as the
main function or in a separate file.
If you put your function after the function containing a
call to your function, or in a separate file, you must
put a prototype (defined in the next slide) for your
function some place in the file where it is called, prior
to the call.
Example: 11 / 2 is 5, NOT 5.5
10 / 3 is 3, NOT 3.333
Even if assigned to a double variable:
double ratio = 10/3; // assigned value is 3, NOT 3.3
9
?
?
?
10
3.3 Programmer Defined Functions
3.3 Programmer Defined Functions
function prototypes
A function is like a small program
A function prototype tells you all the information you need to call
the function. A prototype of a function (or its definition) must
appear in your code prior to any call to the function.
Syntax:
Don’t forget the semicolon
? Type_of_returned_value Function_Name(Parameter_list);
? Place prototype comment here.
? Parameter_list is a comma separated list of parameter
definitions:
type_1 param_1, type_2 param_2, … . type_N param_N
Example:
To understand functions, keep these points in mind:
?
?
?
A function definition is like a small program and calling the
function is the same thing as running this small “program.”
A function has formal parameters, rather than cin, for input. The
arguments for the function are input and they are plugged in for
the formal parameters.
A function of the kind discussed in this chapter does not send
any output to the screen, but does send a kind of “output” back
to the program. The function returns a return-statement instead
of cout-statement for “output.”
double total_weight(int number, double weight_of_one);
// Returns total weight of number of items that
// each weigh weight_of_one
11
12
3.3 Programmer Defined Functions
3.3 Programmer Defined Functions
Display 3.3 A function Definition (Slide 1 of 2)
Display 3.3 A function Definition (Slide 2 of 2)
#include <iostream>
using namespace std;
double total_cost(int number_par, double price_par);
//Computes the total cost, including 5% sales tax,
//on number_par items at a cost of price_par each.
int main( )
{
double price, bill;
int number;
double total_cost(int number_par, double price_par)
{
heading
const double TAX_RATE = 0.05; //5% sales tax
double subtotal;
cout << "Enter the number of items purchased: ";
cin >> number;
cout << "Enter the price per item $";
cin >> price;
bill =
total_cost(number, price);
The function
heading
The function
body
The function
definition
subtotal = price_par * number_par;
return (subtotal + subtotal*TAX_RATE);
}
The function call
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << number << " items at "
<< "$" << price << " each.\n"
<< "Final bill, including tax, is $" << bill
<< endl;
return 0;
13
14
}
3.3 Programmer Defined Functions
3.3 Programmer Defined Functions
Call-by-value Parameters
Alternate form for Function Prototypes
Consider the function call:
bill = total_cost(number, price);
?
?
The values of the arguments number and price are “plugged” in
for the formal parameters . This process is (A precise definition
of what “plugged” means will be presented later. For now, we
will use this simile.)
A function of the kind discussed in this chapter does not send
any output to the screen, but does send a kind of “output” back
to the program. The function returns a return-statement instead
of cout-statement for “output.”
?
The parameter names are not required:
double total_cost(int number, double price);
?
It is permissible to write:
double total_cost(int, double );
?
Nevertheless, code should be readable to programmers as well
as understandable by the compiler, so check for readability and
chose to use parameter names when it increases readability.
Function HEADERS (in the definition) must use parameter
names. (There is an exception to this rule that we will not deal
with in this course.)
?
15
16
3.3 Programmer Defined Functions
3.3 Programmer Defined Functions
Anatomy of a Function Call (part 1 of 3)
Anatomy of a Function Call (part 2 of 3)
Review Display 3.3
0 Before the function is called, the value of the variables number
and price are set to 2 and 10.10, by cin.
1 The following statement, which includes a function call, begins
executing:
bill = total_cost(number, price);
2 The value of number (which is 2) is plugged in for number_par
and the value of price (which is 10.10) is plugged for price_par:
double total_cost(int number_par, double price_par)
{
const double TAX_RATE = 0.05;
//5% sales tax
double subtotal;
subtotal = price_par * number_par;
return (subtotal + subtotal*TAX_RATE);
}
17
The execution produces the following effect:
double total_cost(int 2, double 10.10)
{
const double TAX_RATE = 0.05;
//5% sales tax
double subtotal;
subtotal = 10.10 * 2;
return (subtotal + subtotal*TAX_RATE);
}
18
3.3 Programmer Defined Functions
PITFALL
Anatomy of a Function Call (part 3 of 3)
Arguments in the wrong order
3 The body of the function is executed, i.e., the following is executed:
{
const double TAX_RATE = 0.05;
//5% sales tax
double subtotal;
subtotal = 10.10 * 2;
return (subtotal + subtotal*TAX_RATE);
}
4 When the return statement is executed, the value of the expression after
the return is the value returned by the function. In this case, when
return (subtotal + subtotal*TAX_RATE);
is executed, the value of (subtotal + subtotal*TAX_RATE), which is 21.21
is returned by the function call
bill = total_cost(number, price);
the value of bill is set to 21.21 when the following statement ends:
bill = total_cost(number, price);
?
?
?
When a function is called, C++ substitutes the first argument
given in the call for the first parameter in the definition, the
second argument for the second parameter, and so on.
There is no check for reasonableness. The only things checked
are: i) that there is agreement of argument type with parameter
type and ii) that the number of arguments agrees with the
number of parameters.
If you do not put correct arguments in call in the correct order,
C++ will happily assign the “wrong” arguments to the “right”
parameters.
19
20
3.4 Procedural Abstraction
3.3 Programmer Defined Functions
Principle of Information Hiding
Summary of Syntax for a Function that Returns a Value.
Function Prototype:
Type_Returned Function_Name(Parameter_List);
Prototype Comment
function header
Function Definitions
Type_Returned Function_Name(Parameter_List)
{
Declaration_1
Declaration_2
...
Must include one or
Declaration_Last;
more return statements.
Executable_1;
body
?
David Parnas, in 1972 stated the principle of
information hiding.
?
A function’s author (programmer) should know
everything about how the function does its job, but
nothing but specifications about how the function will be
used.
?
The client programmer -- the programmer who will call
the function in her code -- should know only the function
specifications, but nothing about how the function is
implemented.
Executable_2;
...
Executable_Last
}
21
3.4 Procedural Abstraction
3.4 Procedural Abstraction
The Black Box Analogy
?
?
?
?
22
The Principle
When applied to a function definition, the principle of
procedural abstraction means that your function should be
written so that it can be used like a black box. This means
the user of a function should not need to look at the
internals of the function to see how the function works. The
function prototype and accompanying commentary should
provide enough information for the programmer to use the
function.
To ensure that your function definitions have this property, you
should adhere to these rules:
Based on the Principle of Information Hiding, the text
describes the BLACK BOX analogy.
When using a function, we behave as if we know
nothing about how the function does its job, that we
know only the specifications for the function.
When writing a function, we behave as if we know
nothing but the specifications about how the function
is to be used.
In this way, we avoid writing either application code
that depends on the internals of the function or writing
function code that depends in some way on the
internal structure of the application.
?
?
23
The prototype comment should tell the programmer any
and all conditions that are required of the arguments to
the function and should describe the value returned by
the function.
All variables used in the function body should be
declared in the function body. (The formal parameters
are already declared in the function header.)
24
3.5 Local Variables
3.5 Local Variables
?
?
?
?
Global Constants and Global Variables
?
Variables declared within the body of a function
definition are said to be local to that function, or
have that function’s block as their scope.
Variables declared within the body of the main
function are said to be local to the main function,
or to have that function’s block as their scope.
When we say a function is a local variable
without further mention of a function, we mean
that variable is local to some function definition.
?
?
If a variable is local to a function, you can have
another variable with the same name that is
local to either main or some other function.
A named constant declared outside the body of any
function definition is said to be a global named constant.
A global named constant can be used in any function
definition that follows the constant declaration. There is an
exception to this we will point out later.
Variables declared outside the body any function is said to
be global variables or to have global scope. Such a
variable can be used in any function definition that follows
the constant declaration. There is also an exception to this
we will point out later.
Use of global variables ties functions that use the global
variables in a way that makes understanding the functions
individually nearly impossible. There is seldom any reason
to use global variables.
25
26
Display 3.11 Global Named Constants (Part 1 of 2)
Display 3.11 Global Named Constants (Part 2 of 2)
//Computes the area of a circle and the volume of a sphere.
//Uses the same radius for both calculations.
#include <iostream>
#include <cmath>
using namespace std;
const double PI = 3.14159;
area_of_circle = area(radius_of_both);
volume_of_sphere = volume(radius_of_both);
cout << "Radius = " << radius_of_both << " inches\n"
<< "Area of circle = " << area_of_circle
<< " square inches\n"
<< "Volume of sphere = " << volume_of_sphere
<< " cubic inches\n";
double area(double radius);
//Returns the area of a circle with the specified radius.
return 0;
}
double volume(double radius);
//Returns the volume of a sphere with the specified radius.
double area(double radius)
{
return (PI * pow(radius, 2));
}
int main( )
{
double radius_of_both, area_of_circle, volume_of_sphere;
cout << "Enter a radius to use for both a circle\n"
<< "and a sphere (in inches): ";
cin >> radius_of_both;
double vo lume(double radius)
{
return ((4.0/3.0) * PI * pow(radius, 3));
}
27
28
Display 3.12 Formal Parameter Used as Local Variable
(Part 1 of 2)
3.5 Local Variables
Call-by-value Formal Parameters are Local Variables
?
?
?
?
//Law office billing program.
#include <iostream>
using namespace std;
Formal parameters are more than just blanks to be
filled in with values from arguments.
We promised a more precise discussion of what
“value plugged in for the argument” means. Here is
that discussion.
Formal parameters are actually local variables that are
initialized by the call mechanism to the value of the
argument. They may be used in any way that a local
variable can be used.
Display 3.12 (next slide) is an example of a formal
parameter used as a local variable.
const double RATE = 150.00; //Dollars per quarter hour.
double fee(int hours_worked, int minutes_worked);
//Returns the charges for hours_worked hours and
//minutes_worked minutes of legal services.
int main( )
{
int hours, minutes;
double bill;
29
cout << "Welcome to the offices of\n"
<< "Dewey, Cheatham, and Howe.\n"
<< "The law office with a heart.\n"
<< "Enter the hours and minutes"
<< " of your consultation:\n";
cin >> hours >> minutes;
30
3.5 Local Variables
Display 3.12 Formal Parameter Used as Local Variable
(Part 2 of 2)
Namespaces Revisited (1 of 2)
bill = fee(hours, minutes);
The value of minutes is not
changed by a call to fee.
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << "For " << hours << " hours and " << minutes
<< " minutes, your bill is $" << bill << endl;
All our use of namespaces has amounted to
#include <iostream>
using namespace std;
While this is correct, we are sidestepping the reason
namespaces were introduced into C++, though we have
done this for good teaching reasons.
return 0;
}
minutes_worked is a local variable
initialized to the value of minutes
double fee(int hours_worked, int minutes_worked)
{
int quarter_hours;
In short, we have been “polluting the global namespace.”
So long as our programs are small, so this is not a problem.
This won’t always be the case, so you should learn to put
the using directive in the proper place.
minutes_worked = hours_worked*60 + minutes_worked;
quarter_hours = minutes_worked/15;
return (quarter_hours*RATE);
}
31
32
3.5 Local Variables
3.5 Local Variables
Namespaces Revisited (2 of 2)
Display 3.13 Using Namespaces (1 of 2)
Placing a using directive anywhere is analogous to putting
all the definitions from the namespace there. This is why
we have been polluting the global namespace. We have
been putting all the namespace std names from our
header file in the global namespace.
The rule, then is:
Place the namespace directive,
using namespace std;
inside the block where the names will be used. The next
slide is Display 3.13 with the namespace directive place
correctly.
//Computes the area of a circle and the volume of a sphere.
//Uses the same radius for both calculations.
#include <iostream>
#include <cmath>//Some compilers may use math.h instead of cmath.
const double PI = 3.14159;
double area(double radius);
//Returns the area of a circle with the specified radius.
double volume(double radius);
//Returns the volume of a sphere with the specified radius.
int main( )
{
using namespace std;
double radius_of_both, area_of_circle, volume_of_sphere;
33
cout << "Enter a radius to use for both a circle\n"
<< "and a sphere (in inches): ";
cin >> radius_of_both;
34
3.5 Local Variables
3.6 Overloading Function Names
Display 3.13 Using Namespaces (1 of 2)
area_of_circle = area(radius_of_both);
volume_of_sphere = volume(radius_of_both);
cout << "Radius = " << radius_of_both << " inches\n"
<< "Area of circle = " << area_of_circle
<< " square inches\n"
<< "Volume of sphere = " << volume_of_sphere
<< " cubic inches\n";
?
?
return 0;
}
double area(double radius)
The behavior of this program is exactly
{
the same as that of Display 3.11
using namespace std;
return (PI * pow(radius, 2));
}
double volume(double radius)
{
using namespace std;
return ((4.0/3.0) * PI * pow(radius, 3));
35
}
?
C++ distinguishes two functions by examining the
function name and the argument list for number
and type of arguments.
The function that is chosen is the function with
the same number of parameters as the number of
arguments and and that matches the types of the
parameter list sufficiently well.
This means you do not have to generate names for
functions that have very much the same task, but
have different types.
36
3.6 Overloading Function Names
3.6 Overloading Function Names
Display 3.15 Overloading a Function Name (1 of 2)
Display 3.15 Overloading a Function Name (2 of 2)
//Illustrates overloading the function name ave.
#include <iostream>
double ave(double n1, double n2)
{
return ((n1 + n2)/2.0);
}
double ave(double n1, double n2);
//Returns the average of the two numbers n1 and n2.
double ave(double n1, double n2, double n3);
//Returns the average of the three numbers n1, n2, and n3.
Both these functions have the
same name, but have parameter
lists that are have different
numbers of parameters.
double ave(double n1, double n2, double n3)
{
return ((n1 + n2 + n3)/3.0);
}
int main( )
{
using namespace std;
cout << "The average of 2.0, 2.5, and 3.0 is "
<< ave(2.0, 2.5, 3.0) << endl;
cout << "The average of 4.5 and 5.5 is "
<< ave(4.5, 5.5) << endl;
return 0;
}
?
?
?
37
38
3.6 Overloading Function Names
3.6 Overloading Function Names
Automatic Type Conversion
Display 3.16 Overloading a function name (1 of 4)
We pointed out that when overloading function names, the C++
compiler compares the number and sequence of types of the
arguments to the number and sequence of types for candidate
functions.
In choosing which of several candidates for use when overloading
function names, the compiler will choose an exact match if one if
available.
An integral type will be promoted to a larger integral type if
necessary to find a match. An integral type will be promoted to a
floating point type if necessary to get a match.
//Determines whether a round pizza or a rectangular pizza is the best buy.
#include <iostream>
double unitprice(int diameter, double price);
//Returns the price per square inch of a round pizza.
//The formal parameter named diameter is the diameter of the pizza
//in inches. The formal parameter named price is the price of the pizza.
double unitprice(int length, int width, double price);
//Returns the price per square inch of a rectangular pizza
//with dimensions length by width inches.
//The formal parameter price is the price of the pizza.
int main( )
{
using namespace std;
int diameter, length, width;
double price_round, unit_price_round,
price_rectangular, unitprice_rectangular;
39
3.6 Overloading Function Names
3.6 Overloading Function Names
Display 3.16 Overloading a function name (2 of 4)
Display 3.16 Overloading a function name (3 of 4)
cout << "Welcome to the Pizza Consumers Union.\n";
cout << "Enter the diameter in inches"
<< " of a round pizza: ";
cin >> diameter;
cout << "Enter the price of a round pizza: $";
cin >> price_round;
cout << "Enter length and width in inches\n"
<< "of a rectangular pizza: ";
cin >> length >> width;
cout << "Enter the price of a rectangular pizza: $";
cin >> price_rectangular;
unitprice_rectangular =
unit_price_round =
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
40
cout << endl
<< "Round pizza: Diameter = "
<< diameter << " inches\n"
<< "Price = $" << price_round
<< " Per square inch = $" << unit_price_round
<< endl
<< "Rectangular pizza: length = "
<< length << " inches\n"
<< "Rectangular pizza: Width = "
<< width << " inches\n"
<< "Price = $" << price_rectangular
<< " Per square inch = $" << unitprice_rectangular
<< endl;
if (unit_price_round < unitprice_rectangular)
cout << "The round one is the better buy.\n";
else
cout << "The rectangular one is the better buy.\n";
cout << "Buon Appetito!\n";
unitprice(length, width, price_rectangular);
unitprice(diameter, price_round);
41
return 0;
}
42
Chapter Summary( 1 of 2)
?
?
?
?
?
?
Chapter Summary (2 of 2)
A good plan of attack on a problem is to decompose the problem into smaller, more
accessible problems, the decompose these into still more manageable problems.
This is known as Top-Down Design.
A function that returns value is like a small program. Arguments provide input and
the return value provides the output.
When a subtask for a program takes some values as input and produces a single
value as its only output, then that subtask can be implemented as a function.
A function should be defied so that it can be used as a black box. The program
author should know no more than the specification of the client use, and the client
author should know nothing more than the specification of the implementation of
the function. This rule is the principle of procedural abstraction.
A variable that is defined in a function is said to be local to the function.
Global named constants are declared using the const modifier. Declarations of
global named constants are normally placed at the start of a program after the
include directives, before the function prototypes.
43
?
Call by value formal parameters (the only kind we have discussed so far) are local
variables to the function. Occasionally a formal parameter may be useful as a local
variable.
?
When two or more function definitions have the same name, this is called function
name overloading. When you overload a name, the function definitions must have
different numbers of formal parameters or formal parameters of different types.
44
Download