Title: ACS 168 Structured Programming Using the Computer
1ACS 168Structured Programming Using the Computer
- Chapter 4
- by
- Joaquin Vila
- Prepared
- byShirley White
2Chapter 4 Functions for All Subtasks
- In Chapter 3 we covered how to write functions
that return one value. - Here we see how to design functions that perform
other kinds of subtasks.
34.1 void-Functions
- Void functions return no values at all.
- Such a function is called a void-function. The
essential point is demonstrated here - void Print( double value)
-
- using namespace std
- cout ltlt value ltlt endl
-
3
4Definition of void-Functions
- A C void-function is defined similarly to
functions that return a value. - There are three differences between value
returning functions and void-functions. - void type
- There is no return expression statement.
- A call to a void-function is an executable
statement, rather than being part of an
expression.
4
5Code from Page 175
- void show_results(double f_degrees, double
c_degrees) -
- using namespace std
- cout.setf(iosfixed)
- cout.setf(iosshowpoint)
- cout.precision(1)
- cout ltlt f_degrees
- ltlt degrees Fahrenheit is
equavalent to\n - ltlt c_degrees ltlt degrees
Celsius\n -
6- Calling (invoking) the function
show_resultsshow_results(32.5, 0.3)32.5
degrees Fahrenheit is equivalent to0.3 degrees
Celsius.
7Display 4.1 Syntax for a void-Function Definition
- //void-Function Prototype
- void Function_Name(Parameter_List)
- //void-Function Definition
- void Function_Name(Parameter_List)
Function header -
- Declaration_1
You may intermix declarations - Declaration_2
and executable statements. - . . .
- Declaration_Last
- Executable_1
Executables may or may not - Executable_2
include one or more return - . . .
statements. - Executable_Last
8return-Statements in void-Functions
- In C both void functions and value-returning
functions can have return statements. - In value-returning functions the return is
required and must have an argument. In
void-functions, the return is optional and must
NOT have an argument. - There is an implicit (compiler generated) return
statement at the final closing brace of a void
function. This does not mean you never need a
return in a void-function.
8
9Display 4.2 void-Function (1 of 4)
- //Program to convert a Fahrenheit temperature to
a Celsius temperature. - include ltiostreamgt
- void initialize_screen( )
- //Separates current output from the output
- //of the previously run program.
- double celsius(double fahrenheit)
- //Converts a Fahrenheit temperature to a Celsius
temperature. - void show_results(double f_degrees, double
c_degrees) - //Displays output. Assumes that c_degrees
- //Celsius is equivalent to f_degrees Fahrenheit.
- int main( )
-
- using namespace std
- double f_temperature, c_temperature
10Display 4.2 void-Function (2 of 4)
- cout ltlt "I will convert a Fahrenheit
temperature" - ltlt " to Celsius.\n"
- ltlt "Enter a temperature in
Fahrenheit " - cin gtgt f_temperature
- c_temperature celsius(f_temperature)
- show_results(f_temperature, c_temperature)
- return 0
-
11Display 4.2 void-Function (3 of 4)
- //Definition uses iostream
- void initialize_screen( )
-
- using namespace std
- cout ltlt endl
- return This return is
optional. -
- double celsius(double fahrenheit)
-
- return ((5.0/9.0)(fahrenheit - 32)) This
return is required.
12Display 4.2 void-Function (4 of 4)
- //Definition uses iostream
- void show_results(double f_degrees, double
c_degrees) -
- using namespace std
- cout.setf(iosfixed)
- cout.setf(iosshowpoint)
- cout.precision(1)
- cout ltlt f_degrees
- ltlt " degrees Fahrenheit is equivalent
to\n" - ltlt c_degrees ltlt " degrees
Celsius.\n" - return // This return is optional.
-
134.2 Call-by-Reference Parameters
- Often we need to return multiple values and for
that we need another mechanism - Call-by-Reference.
- With a Call-by-Value parameter, the corresponding
argument is only read for its value. The argument
can be a variable, but this is not necessary. The
parameter is initialized with the value of the
value-parameter and changing it within the
function does not effect the value in the calling
function. - With Call-by-Reference, the corresponding
argument must be a variable, and the behavior of
the function is as if the variable were
substituted for the parameter.
This is like making a copy of the variables
value and passing it to the function. The copy
may be changed, but that does not effect the
original value.
This is like passing the actual variable to the
function. When changes are made they effect the
actual variable.
13
14A first view of Call-by-reference
- To make a parameter a call-by-reference,
parameter, an ampersand ( ) is placed between
the type name and the variable name in the
function header and in the prototype that is used
to declare this function. - a call-by-reference parameter
- Example
- void Get_Input( double f_variable)
-
- using namespace std
- cout ltlt Enter a Fahrenheit temp, I will
return Celsius\n - cin gtgt f_variable
14
15Display 4.4Call by Reference parameters (1 of 2)
- //Program to demonstrate call-by-reference
parameters. - include ltiostreamgt
- void get_numbers(int input1, int input2)
- //Reads two integers from the keyboard.
- void swap_values(int variable1, int variable2)
- //Interchanges the values of variable1 and
variable2. - void show_results(int output1, int output2)
- //Shows the values of variable1 and variable2, in
that order. - int main( )
-
- int first_num, second_num
- get_numbers(first_num, second_num)
- swap_values(first_num, second_num)
- show_results(first_num, second_num)
- return 0
The ampersands used here indicate these functions
use call-by-reference
This function is a call-by-value.
Notice no ampersand appears in the calls.
16Call by Reference parameters (2 of 2)
- //Uses iostream
- void get_numbers(int input1, int input2)
-
- using namespace std
- cout ltlt "Enter two integers "
- cin gtgt input1
- gtgt input2
-
- void swap_values(int variable1, int variable2)
-
- int temp
- temp variable1
- variable1 variable2
- variable2 temp
-
- //Uses iostream
The ampersands were used in the prototypes AND
the function headers.
17Call-by-Reference in Detail
- A call-by-value parameter actually requires the
value stored in the varialbe to be copied (taking
up additional memory space) and transferred into
the parameter. - Saying that a call-by-reference parameter has the
argument variable copied into the parameter isnt
completely true. - The whole truth is the address of the argument
is used in place of the parameter, and the
address is used to fetch values from the argument
as well as to write to the argument. - This does not take additional memory space, but
it does mean the function has direct access to
the place where the variable value is stored.
That is why changes are permanent.
17
18 Parameters and Arguments (1 of 2)
- If you keep these points in mind, you can handle
all the parameter passing language. - 1. The formal parameters for a function are
listed in the function prototype and function
definition header. A formal parameter is a place
holder that is filled at the time the function is
called. - 2. Arguments appear in a comma separated list
in the call to the function, and are used to fill
in the corresponding formal parameters. When the
function is called, the arguments are plugged
in for the formal parameters. - 3. The terms call-by-value and call-by-reference
refer to the mechanism that is used in the
plugging in process.
18
19 Parameters and Arguments (2 of 2)
- In the call-by-value method, the arguments are
read, and the parameters are initialized using a
copy of the value of the argument. - I can give you a copy of my book to write in, but
my book remains unchanged no matter what you do. - In the call-by-reference method, the argument
must be a variable. The behavior is exactly as if
the argument were substituted for the parameter.
Here if the function changes the parameter, the
original argument is also changed. - If I give you my book, any changes you make are
there when you return it to me. - The address of the argument is passed so the
receiving function knows where the argument is
stored. When the value is changed in the
function, the arguments actual storage location
is where the writing is done.
19
20 Mixed Parameter Lists
- It is entirely feasible to have value parameters
(call-by-value parameter) mixed in with
reference parameters (call-by-reference
parameters). - (We tend to use short cuts in the language.)
- Example
- void good_stuff(int par1, int par2, double
par3) - Call good_stuff( arg1, 17, arg3)
- Here 17 is permissible because par2 is a value
parameter. - This code may (but by no means must) change arg1
and arg3.
20
21 PITFALL Inadvertent Local Variables
- Omitting an ampersand () when you intend to use
a reference parameter is a mistake that bites
twice. First it makes your code run incorrectly
but the compiler probably wont catch it. Second
the error is very difficult to find because it
looks right.
21
22Display 4.7 Inadvertent local variables
- //Inadvertent local variables. Shows what happens
when you omit - //Program to demonstrate call-by-reference
parameters. - include ltiostreamgt
- void get_numbers(int input1, int input2)
- //Reads two integers from the keyboard.
-
Forgot the here - void swap_values(int variable1, int variable2)
- //Interchanges the values of variable1 and
variable2. - void show_results(int output1, int output2)
- //Shows the values of variable1 and variable2, in
that order. - int main( )
-
- using namespace std
23Inadvertent local variables (2 of 2)
- void swap_values(int variable1, int variable2)
-
- int temp
- temp variable1 Forgot the
here, which - variable1 variable2 Makes these
inadvertent local variables - variable2 temp
-
- //Uses iostream
- void get_numbers(int input1, int input2)
-
- using namespace std
- cout ltlt "Enter two integers "
- cin gtgt input1
- gtgt input2
-
- //Uses iostream
24Display 4.8 Function Calling Another Function (1
of 2)
- //Program to demonstrate a function calling
another function. - include ltiostreamgt
- void get_input(int input1, int input2)
- //Reads two integers from the keyboard.
- void swap_values(int variable1, int variable2)
- //Interchanges the values of variable1 and
variable2. - void order(int n1, int n2)
- //Orders the numbers in the variables n1 and n2
- //so that after the function call n1 lt n2.
- void give_results(int output1, int output2)
- //Outputs the values in output1 and output2.
- //Assumes that output1 lt output2
- int main( )
- Start in main
- Declare variables
- Call get_input() where the values for input1 and
input2 are returned to first_num and second_num
(in main) - Call order()
- If n1 gt n2 then call swap_values() which trades
the order of the variables then returns to
order(), which returns the values to main - Call give_results() which prints the values in
increasing order and returns to main - Where the program ends.
25Function Calling Another Function (2 of 2)
- //Uses iostream
- void get_input(int input1, int input2)
-
- using namespace std
- cout ltlt "Enter two integers "
- cin gtgt input1 gtgt input2
-
- void swap_values(int variable1, int variable2)
-
- int temp
- temp variable1
- variable1 variable2
- variable2 temp
- void order(int n1, int n2)
-
- if (n1 gt n2)
- swap_values(n1, n2)
-
- //Uses iostream
- void give_results(int output1, int output2)
-
- using namespace std
- cout ltlt "In increasing order "
- ltlt "the numbers are "
- ltlt output1 ltlt " " ltlt output2
- ltlt endl
-
26Preconditions and Postconditions
- The Prototype comment should be broken into a
precondition and a postcondition. - The precondition is what is required to be true
when the function is called. - The postcondition describes the effect of calling
the function, including any returned value and
any effect on reference parameters.
27Preconditions and Postconditions
- Example Pre - and Post-conditions.
- // square root function, sqrt
- // Prototype
- double sqrt( double arg)
- // Pre arg gt 0
- // Post returned value squared arg
- If the Precondition is satisfied the function
promises to put the Postcondition true. - If the precondition is not satisfied, the
functions behavior is not constrained in any way.
284.4 Testing and Debugging Functions
- Every function should be designed, coded and
tested as a separate unit from the rest of the
program. - Every new function should be tested in a program
in which every other function in that program has
already been completely tested and debugged. - Therefore you need a tested and working framework
to develop and test your functions. - This is the essence of the top-down design
strategy. - How do you test a function? By writing a simple,
short program called a driver that calls the
function. The driver should be simple enough that
we can confirm its correctness by inspection.
29Stubs and Drivers
- How do you test a program that needs a function,
before you have written the function? - By writing a simple, short program called a stub
that provides the the program with the same
prototype, and provides enough data to the caller
so the caller can be tested. - Again,the stub should be simple enough that we
can confirm its correctness by inspection.
30Stubs and Drivers
- First, write stubs for all the functions.
- Then write the real functions, putting them into
the program one at a time. - This way the complete program and already written
code continues to be tested, while the new
functions are written and tested until the final
program is produced.
31Fundmental Rule for Testing Functions
- Every function should be tested in a program in
which every other function in that program has
already been completely tested and debugged.
32Display 4.11Program that uses a Stub (part 1 of
4)
- //Determines the retail price of an item
according to - //the pricing policies of the Quick-Shop
supermarket chain. - include ltiostreamgt
- void introduction( )
- //Postcondition Description of program is
written on the screen. - void get_input(double cost, int turnover)
- //Precondition User is ready to enter values
correctly. - //Postcondition The value of cost has been set
to the - //wholesale cost of one item. The value of
turnover has been - //set to the expected number of days until the
item is sold. - double price(double cost, int turnover)
- //Precondition cost is the wholesale cost of one
item. - //turnover is the expected number of days until
sale of the item. - //Returns the retail price of the item.
33Program that uses a Stub (part 2 of 4)
- void give_output(double cost, int turnover,
double price) - //Precondition cost is the wholesale cost of one
item turnover is the - //expected time until sale of the item price is
the retail price of the item. - //Postcondition The values of cost, turnover,
and price have been - //written to the screen.
- int main( )
-
- double wholesale_cost, retail_price
- int shelf_time
- introduction( )
- get_input(wholesale_cost, shelf_time)
- retail_price price(wholesale_cost,
shelf_time) - give_output(wholesale_cost, shelf_time,
retail_price) - return 0
34Program that uses a Stub (part 3 of 4)
- //Uses iostream
- void introduction( )
-
- using namespace std
- cout ltlt "This program determines the retail
price for\n" - ltlt "an item at a Quick-Shop supermarket
store.\n" -
- //Uses iostream
- void get_input(double cost, int turnover)
-
- using namespace std
- cout ltlt "Enter the wholesale cost of item "
- cin gtgt cost
- cout ltlt "Enter the expected number of days
until sold " - cin gtgt turnover
35Program that uses a Stub (part 4 of 4)
- //Uses iostream
- void give_output(double cost, int turnover,
double price) -
- using namespace std
- cout.setf(iosfixed)
- cout.setf(iosshowpoint)
- cout.precision(2)
- cout ltlt "Wholesale cost " ltlt cost ltlt endl
- ltlt "Expected time until sold "
- ltlt turnover ltlt " days" ltlt endl
- ltlt "Retail price " ltlt price ltlt endl
-
- //This is only a stub
- double price(double cost, int turnover)
-
- return 9.99 //Not correct, but good enough
for some testing.
36Summary (1 of 2)
- All subtasks in a program can be implemented as
functions, either as void-functions or
value-returning functions. - A formal parameter is a kind of place holder
that is filled with a function argument when the
function is called. The two mechanisms for
filling are call-by-value and call-by-reference. - In call-by-value, the value of the argument is
copied into the parameter. With call-by-reference
the argument must be a variable, and the effect
is as if the variable had been substituted for
the parameter. - The syntax to make a parameter call-by-reference
is to insert an ampersand () between the type
and the parameter in the function prototype and
function header. - An argument corresponding to a call-by-value
parameter will not be changed by the call. An
argument corresponding to a call-by-reference
parameter may be changed by the call, but this is
not necessary. To make a function change an
argument, the corresponding parameter must be
call-by-reference.
37Summary (2 of 2)
- Function prototype comments should be divided
into Preconditions and Postconditions. The
precondition describes the requirements that must
be in effect when the function is called, and the
postconditions describe the effect of the call,
including any returned value and/or changed
arguments. - Every function should be tested in a completely
tested and debugged program. - A driver program is a short program that does
nothing but test a function. - A stub is a simplified function used in place of
a function definition that has not yet been
tested (perhaps not written) so that the rest of
the program can be tested.