Please send questions to
st10@humboldt.edu .
CIS 130 - Week 14, Wednesday - April 28, 2010
DEBUGGING TIP:
* you have a function -- it compiles -- but,
oh no!! the test returns false!!
What are some options in figuring out what's
up?
--> sometimes, it is very useful to TEMPORARILY
stick in some cout statements JUST for
debugging, to see what's going on;
* simplest case: you might stick in a
cout (after your test cout) that simply
prints the value of the test call --
(you can see, then, "how far off" it is --
is this an expected double and an actual
double that are actually quite close,
or a real problem?)
* when you need to dig deeper:
* you might put a cout at the beginning
of each function called in a program,
to see if all are being called;
* you might output the values of
its parameters at that beginning
cout, to see if the function is being
called properly;
* you might cout 1, then 2, then 3,
say before each major part of your
function (and perhaps within each
loop and within each branch), so
you can see if the execution "flow"
is what you expect;
* cout the values of key variables
(parameters and/or arguments) at
various points as seems useful
demo: debugging a buggy get_max function
using debugging couts:
* original: buggy_get_max.cpp
* with debugging couts: couted_get_max.cpp
* corrected/final: final_get_max.cpp
TWO MORE PASS-BY-REFERENCE EXAMPLES
another relatively common use of pass by reference parameters:
* is to permit a function to give back more than one value
to the calling function --
* a function can ONLY return ONE value!!!!!
* BUT!! a function can have multiple pass-by-reference
parameters, serving as output parameters,
intended to be set by the function to those
multiple values you want to get back to the
calling function...
* (do consider: would you be better served by writing
multiple functions instead?
...but if the answer is no, proceed...)
* silly-but-simple example:
I want a function that expects a first name and a last
name, and I want it to result in two versions of the
corresponding full name:
* one that is last name, comma, blank, first name
* one that is first name, space, last name
* call it get_full_names
* get_full_names CANNOT return two values!
...but it COULD return one, and give the other
back via a pass-by-reference parameter;
...or, it could give both back via pass-by-reference
parameters.
I'm picking the second option, mostly because
I don't see a logical reason to treat the full names
differently, and for more pass-by-reference practice...
//contract: get_full_names: string string string& string& -> void
/* purpose:
expects a first name and a last name as input parameters,
and also has two string output parameters;
it does not return anything, but the first output
parameter is set to the full name, last name then comma
then blank then first name, and the second output
parameter is set to the full name, first name then
blank then last name
*/
void get_full_names(string first_name, string last_name, string& last_then_first, string& first_then_last)
examples:
string last_first;
string first_last;
get_full_names("Charles", "Schulz", last_first, first_last);
after this call:
last_first == "Schulz, Charles"
first_last == "Charles Schulz"
* NOTE: if you aren't using funct_play2, remember to create
a .h file for each non-main function in your program;
you can use the .h template on the public course web page
to remind you of its structure
(the #ifndef and #define, if followed by the function name then
underscore h, will make sure that your functions aren't doubly-defined
if more than function calls them)
2nd example: a function that expects an array of doubles, and its size,
and I'd LIKE the sum AND the average of its values;
...I could return one and get the other back by pass-by-reference,
or I could make both pass-by-reference, and I'll choose that
for more pass-by-reference experience;
// contract: sum_plus_avg: double[] int double& double& -> void
see: sum_plus_avg