Here are a few questions to help you clarify your understanding of the middling aspects of writing your own functions — reference arguments.
How many values can a function return through its return value mechanism?
one (or none)
But we learned that a function can 'return' many values! How is this possible?!
By using the reference mechanism of argument passing the function gains write access to the caller's memory locations. With two or more references, a function can write two or more value for the caller. Thus we can effectively give the caller back multiple values upon our return.
Can a function with a void return type send any value(s) back to the caller? If so, how?
Of course! By using the reference mechanism. It gives the function write access to the caller's memory locations. The function can store results directly into the caller's variables for it to use upon the function's return.
How many return statements should a function have?
one and only one
Should a function with a void return type have a return statement?
YES!!!
How many values can you place on a return statement?
one (or none)
Why might a programmer make a function argument a constant reference? (Hint: What does each do? What would their combined meaning then be?)
The reference avoids a copy into local memory space by linking directly to the caller's memory location. Although this normally allows write access to the caller's memory, the const keyword removes this ability. So, the overall effect of the constant reference is a faster call than a typical by-value passing.
Show a function to read the time-of-day from the user in a normal format. (Thought-provoker: should you require the caller to prompt to make your function more general or is there a better way?)
This version requires the caller to prompt: void read_time(short & hour, short & minute, short & second) { char t; cin >> hour >> t >> minute >> t >> second; return; } This version allows the caller to pass us a prompt, keeping our user interaction as generic as possible: void read_time(short & hour, short & minute, short & second, const string & prompt) { char t; cout << prompt; cin >> hour >> t >> minute >> t >> second; return; }
Show a call to your function (and all necessary supporting code). (If you feel more than one call would help clarify your function's use, please feel free to do so.)
Here's a possible call to the first version: short class_hr, class_min, class_sec; cout << "Enter the time class begins: "; read_time(class_hr, class_min, class_sec); Or, to call the second version: short class_hr, class_min, class_sec; read_time(class_hr, class_min, class_sec, "Enter the time class begins: "); As we can see, either way, the prompt is separate from the actual function. It is chosen by the caller. It can therefore be changed to fit the needs of any particular situation, like so: short show_hour, show_min, show_sec; cout << "What time does your show start? "; read_time(show_hour, show_min, show_sec);
Write a function to read a 2D point from the user in a normal format. (Thought-provoker: should you require the caller to prompt to make your function more general or is there a better way?)
This version requires the caller to prompt: void read_point(double & x, double & y) { char t; cin >> t >> x >> t >> y >> t; return; } This version allows the caller to pass us a prompt, keeping our user interaction as generic as possible: void read_point(double & x, double & y, const string & prompt) { char t; cout << prompt; cin >> t >> x >> t >> y >> t; return; }
Now show two calls to your function (and all necessary supporting code) to gather the upper left corner and lower right corner coordinates of the user's rectangle.
Here's a possible call to the first version: double x_begin, y_begin, x_end, y_end; cout << "Enter the beginning coordinates: "; read_point(x_begin, y_begin); cout << "Enter the ending coordinates: "; read_point(x_end, y_end); Or, to call the second version: double x_begin, y_begin, x_end, y_end; read_point(x_begin, y_begin, "Enter the beginning coordinates: "); read_point(x_end, y_end, "Enter the ending coordinates: "); As we can see, either way, the prompt is separate from the actual function. It is chosen by the caller. It can therefore be changed to fit the needs of any particular situation.
Show a function which reads [all of] the user's initials (along with the standard trailing periods) and returns [all of] the initials to the caller. (Thought-provoker: should you require the caller to prompt to make your function more general or is there a better way?)
This version requires the caller to prompt: void read_init(char & first, char & second, char & third) { char t; cin >> first >> t >> second >> t >> third >> t; return; } This version allows the caller to pass us a prompt, keeping our user interaction as generic as possible: void read_init(char & first, char & second, char & third, const string & prompt) { char t; cout << prompt; cin >> first >> t >> second >> t >> third >> t; return; }
Now show a call to your function (and all necessary supporting code).
Here's a possible call to the first version: char player_1_fi, player_1_mi, player_1_li, player_2_fi, player_2_mi, player_2_li; cout << "What are the first player's initials? "; read_init(player_1_fi, player_1_mi, player_1_li); cout << "What are the second player's initials? "; read_init(player_2_fi, player_2_mi, player_2_li); Or, to call the second version: char player_1_fi, player_1_mi, player_1_li, player_2_fi, player_2_mi, player_2_li; read_init(player_1_fi, player_1_mi, player_1_li, "What are the first player's initials? "); read_init(player_2_fi, player_2_mi, player_2_li, "What are the second player's initials? "); As we can see, either way, the prompt is separate from the actual function. It is chosen by the caller. It can therefore be changed to fit the needs of any particular situation.
What is meant by the term 'input/output argument'?
This term represents an argument to a function which both has a value of initial use to the function and whose value is changed to produce output to the caller.
How does this differ from 'function input' or 'function output'?
It is a combination of the two. A function input is a value useful to the function and therefore requested of its caller. A function output is a value produced by a function for the caller. An input/output argument is both of these things in one.
TRUE✓ | FALSE✗ | Having a function take string arguments can extend its usefulness to many new situations. | ||
---|---|---|---|---|
TRUE✓ | FALSE✗ | Such string arguments are often 'fast-pass-by-value' (which means they must be modified with the keyword const and the symbol & ). | ||
TRUE✓ | FALSE✗ | The actual arguments passed to these functions can be either string variables, string constants, or even literal strings. |
The following function is terribly program specific:
double input(void) { double pay; cout << "Enter your pay rate: "; cin >> pay; return pay; }
To fix it, we could do something like this:
// caller must prompt before calling us!!! double input(void) { double x; cin >> x; return x; }
But with strings, we can print the prompt from the function and still have the function be completely generic — letting the caller tell us what the prompt should be on each call.
(After all, is string data any different than other data we've parameterized? Just its type...)
Show how this can be done by filling in the blanks below:
double input( const string & prompt ) { double x; cout << prompt ; cin >> x; return x; }
Now show two or more calls to your new input function that demonstrate its genericity and utility.
double budget, spent; budget = input("What was your departmental budget last quarter? "); spent = input("And what was your department's expenditure last quarter? ");
Write a function which can change its [single] string argument to all uppercase. The result should be 'given back to' the caller.
This could be done in one of two ways. An inefficient method would be to take a copy of the caller's string, change it, and return a copy of it: string toupper(string s) { for (string::size_type c = 0; c != s.length(); c++) { s[c] = toupper(s[c]); } return s; } A more efficient method would be to take a reference to the caller's string and change it in place: void toupper(string & s) { for (string::size_type c = 0; c != s.length(); c++) { s[c] = toupper(s[c]); } return; }