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