User defined functions
We assume for your prior programming experience in CMSC 201
that you are familiar with writing functions. This includes
- Functions that return a value
- Functions that do not return a value (void functions)
- Functions with parameters (including structs and arrays)
- Functions with no parameters
- Functions that call other functions
Functions provide a form of "procedural abstraction". The user of
a function need not know how a function works in order
to use it. The term abstraction conveys the idea that you
are hiding the details of the code contained in the function.
This is often referred to as treating the function like
a black box.
Documentation about what a function does is contained in the function
header comment which is found the header file that contains the
function's prototype.
In this course, we have a requirement that all function header
comments contain pre- and post-conditions. This information assists
the user in understand what the function does. Thinking about
pre- and post-conditions are important when designing your functions.
Pre-Conditions and Post-Conditions
A pre-condition is a statement of what the function assumes to be
true when it is called. The function should not be called and cannot
be expected to perform correctly unless all pre-conditions are met.
Pre-conditions always include some statement about the state
of the arguments to the function.
A post-condition is a statement that describes the effect
of the function (assuming all preconditions are met). For functions that
return a value, the post-condition will always describe the value returned.
For functions that change the value of some argument(s), the post-condition
will describe the changes.
- More than a summary of what the function does
- First step in design of a function (along with prototype)
- Form a "contract" between function writer and function user
Examples from text page 115.
Right
| Wrong
|
//------------------------------------------------------
// Function: ShowInterest
// PreCondition:
// balance is a nonnegative savings account balance
// rate is the interest rate expressed as a percent
// such as 5 for 5%
// PostCondition:
// the amount of interest for the given balance at the
// given rate is displayed to cout.
// if the parameters are invalid, "No Interest" is displayed
//-------------------------------------------------------
void ShowInterest( double balance, double rate )
{
if (balance >= 0 && rate >=0)
{
// code to calculate and display interest
} else {
cout << "No Interest\n";
}
}
|
//------------------------------------------------------
// Function: ShowInterest
// PreCondition:
// passes in the balance and rate <-------- WRONG
// PostCondition:
// the amount of interest for the given balance at the
// given rate is displayed to cout <-------- OK
//
//
//
//-------------------------------------------------------
void ShowInterest( double balance, double rate )
{
// code to calculate and display interest
}
|
//-------------------------------------------------------
// Function: Area
// PreCondition:
// radius is positve
// PostCondition:
// returns the area of a circle with given radius
// returns 0.0 if radius is invalid
//-------------------------------------------------------
double Area( double radius )
{
const double PI = 3.14159;
if ( radius > 0 )
return 2 * PI * radius * radius;
else
return 0.0;
}
|
//-------------------------------------------------------
// Function: Area
// PreCondition:
// passes in the double radius <-------- WRONG
// PostCondition:
// returns the double area <-------- OK, not great
//
//-------------------------------------------------------
double Area( double radius )
{
const double PI = 3.14159;
return 2 * PI * radius * radius;
}
|
What do we do if the pre-conditions are not met?
There are a couple of basic methods for handling pre-conditions which are not met.
All pre-conditions which are not met must be handled in some manner.
- Handle the invalid pre-condition if possible as in the examples above
- Return a status (via return value or reference parameter) indicating that an
error occurred.
- Alert the caller by throwing an exception (later this semester)
- As a last resort, abort the program execution using the assert() or exit( ) function
Of these, alerting the caller is preferred. However, until we learn proper
exception handling, we are stuck with the other options. As the function
designer, you must choose which method to use.
Unless exiting via exit( ), or your function's purpose is to input data,
DO NOT output a message to the user and/or prompt the user for new input.
Exercises
Write the function header comment (including pre- and post-conditions)
and function prototype for the following functions. Then write the code.
- A function named FindMax that searches an array of
integers and returns the index of the first occurrence of the maximum value in the array.
- A function named PrintGreeting that outputs a user-supplied
message to the standard output.
- A function named FindSmallest that returns the
smallest of three integers.
- A function named Volume that returns the volume of a sphere
with a given radius. The formula for the volume of a sphere is given on
page 121 of the text.
- A function named Speed that returns the speed of a
vehicle in miles per hour, given the distance traveled and the time to travel
that distance.
Last Modified: Monday, 28-Aug-2006 10:16:00 EDT