Topics:
A. In this part of the lab we will implement a function that uses reference parameters.One of the main uses
for reference parameters is to return a value from a function. In the simplest case where a function return only
one value, this can be accomplished either by a function that returns a value or we can add an extra reference
parameter to the parameter list and return the value that way. In the case where we want to return (or change)
more than one value ( swap(x.y) for example), our only choice is to use reference parameters. To illustrate this,
we will first implement a function that returns a value - then we will modify the function to have a return value
of type void and instead, return the value using a reference parameter. Write two functions, called valHypotenuse
and refHypotenuse
. The prototypes for the two functions are:
doublevalHypotenuse
(double a, double b); //function returning a value voidrefHypotenuse
(double a, double b, double& x); //function using reference parameter to return value
The purpose of both of the functions is the same - to compute the hypotenuse of a triangle, given the length
of the other two sides. The first version is a value returning function that "returns" the answer to
the calling statement (x = valHypotenuse(a,b);
) , whereas the second version returns the answer in
the reference parameter x
(refHypotenuse(a,b,x);
). Write a C++ program (yourLastNameLab8Part1a.cpp)
that implements each function as given above and write a main function to test them both. Call each function with
least three test cases. A test case should look something like this:
//assume all variables have been declared
//test case one
x = 0;
a = 3;
b = 4;
x = valHypotenuse(a,b);
cout << "Call by value: a = " << a << " b = " << b << "
hypotenuse = " << x << endl;
//could also call like this since it returns a value
//cout << "Call by value: a = " << a << " b = " << b << "
hypotenuse = " << valHypotenuse(a,b) << endl;
x = 0; //reset x to ensure next call really changes the value
refHypotenuse(a,b,x); //note call on single line - no return value - also do not use & in function call
cout << "Call by reference: a = " << a << " b = " << b << "
hypotenuse = " << x << endl;
//test case two
//test case three
(Note: you do not need to prompt the user for input - simply assign values to the variables and call the function). Use the same set of values for both function call and ensure they are each returning the same answers. Finally enable the debugger and use it to trace the execution of the program - note how the function changes the value of the reference parameter.
B. Consider a function called rightShift
which accepts four(4) integer parameters, and shifts their
values to the right by one - the last value "wraps around" to become the first value. For example (4,
5, 6, 7) becomes (7, 4, 5, 6) - (13, 67, 45, 1) becomes (1, 13, 67, 45). In this problem, our only option is to
use reference parameters since we need to change the value of four variables.
The function to implement rightShift
should have exactly four parameters, and will not return a
value. An example call to rightShift
would be:
w=4; x=5; y=6; z=7;
rightShift(w, x, y, z);
after which the values of w, x, y, and z would be shifted as described above (w=7, x=4, y=5, z=6).
(Note: you do not need to prompt the user for input - simply assign values to the variables and call the
function).
Write a C++ program (yourLastNameLab8Part1b.cpp) that implements and tests the function rightShift
.
You will need a main, a function prototype and the function body.
IMPORTANT -- Follow the design process outlined in lab 7.
rightShift
using the sample code below. Notice the code does nothing other than indicate
that the function has been called and displays the values of the incoming parameters. An interim function implementation
like this is called a stub. A stub is an incomplete function that displays the value(s) of the arguments
passed to it. Among other things, test stubs can be used to verify that a function has been called at an appropriate
moment, even if the entire function has not yet been implemented. This supports incremental development of large
programs and is a widely-used practice in industry.
//your function heading here
{
cout << "rightShift
under construction: ";
cout << "w = " << w << " x = " << x << " y = " << y << " z = " << z << endl;
}
main
function to test the rightShift
test stub.
int main() { int w=4, x=5, y=7, z=8; cout << "BeforerightShift
: w="<<w<<" x="<<x<<" y="<<y<<" z="<<z<<endl;rightShift
(w, x, y, z); cout << "AfterrightShift
: w="<<w<<" x="<<x<<" y="<<y<<" z="<<z<<endl; //put your other tests here return 0; }
rightShift
, the message: rightShift under construction:
w=4 x=5 y=7 z=8
should appear. Now that you have verified the flow and logic of the driver function, we
can implement the function.
rightShift
that implements the function as described earlier. Remember,
you will need a temp variable when swapping two or more values.
rightShift
when the function is working correctly.
Function overloading allows us to use the same name for two or more different functions as long as the number or type of parameters is different.
A. Convert the program from lab7-Part3 so that the largest and smallest function works for floating point numbers as well as integers (yourLastNameLab8Part2a.cpp). This means that you will have to overload the functions - i.e. for each function (smallest, largest), you will have two functions with the same name, the function prototypes will have the same name but the type of the parameters will be different. You will also have two function bodies that differ in the type of parameters as well as their implementation. Write a main function (driver) that will test your functions - you should include before and after print statements (as shown above) to show the result of each function call. Your main should follow the model shown below for calls to your functions: Run the program and verify that it is working. Enable the debugger and run the program again - verify that the correct function get called.
int a, b, c, d;
double w, x, y, z;
//assign values for a, b, c
//print before message for min
d = min(a,b,c);
//print after message for min
//assign values for a, b, c
//print after message for max
d = max(a,b,c);
//print after message for max
//assign values for x, y, z
//print before message for min
z = min(w,x,y)
//print after message for min
//assign values for x, y, z
//print before message for max
z = max(w,x,y)
//print after message for max
Next consider what happens if I mix data types when calling largest or smallest?? For example assume a
,
b and c are ints and x
, y and z
are doubles, what happens when we execute this
z = largest(a,x,y) or c = smallest(x,a,b);
Try 2 calls similar to these and note the results by adding comments
to the source code stating your conclusion about the call and what happens - enable the debugger for clues. Comment
out your tests before going on.
B. Create a C++ program (yourLastNameLab8Part2b.cpp) and add a function called averager
, which
accepts two integer parameters and returns their average as an integer value. Also add an appropriate main()
to test averager
and ensure that it is working correctly.
averager
that passes it integer values (result=averager(7, 9)
), then
try a call to averager
that passes it characters (result=averager('z', 'a')
). Then try
a call using doubles (result=averager(5.2, 1.4)
). Finally try a call that mixes doubles and interers
(result=averager(17.5, 23)
). (Again use the model above for tests - before message, function call,
after message ...). Enable the debugger, run the program, and track the value of the variables. What happens to
the data that is passed to the functions - in particular, note the type conversion that takes place.
averager
so that it accepts two doubles and returns the result as a double. (comment
out the current version of averager
for now - but don't delete it because you need it in the next
step). Repeat the tests you did in the above steps (Just run the program again with the debugger enabled).
averager
into the program (i.e., both the integer version
and the double version) and try running it.
ambiguous access to overloaded function 'averager(int, int)' 'averager(double,
double)'
. This happens because the compiler can't determine which function to call. Remove the tests which
utilize a mixture of input types on the same call, and repeat the remaining tests. Use the debugger to verify that
the integer version of averager
is called when integer parameters are used, and that the double version
is called when double parameters are used.