I succeeded in the first part of the exercise, this attempt is the second part. I am not sure I have accomplished the goal, and would appreciate the input of more knowledgeable minds. As always, critiques of my techniques welcome.
This is an exercise from the book titled 'Beginning C++ through Game Programming' by Michael Dawson.
Challenge me, despite my novice level of understanding.
The exercise:
Using default arguments, write a function that asks the user for a number and returns that number. The function should accept a string prompt from the calling code. If the caller doesn't supply a string for the prompt, the function should use a generic prompt.
Next, using function overloading, write a function that achieves the same results.
My code:
// Chapter 05, Exercise 03: Beginning C++ through Game Programming
/* Using default arguments, write a function that asks the user for a
number and returns that number. The function should accept a string
prompt from the calling code. If the caller doesn't supply a string
for the prompt, the function should use a generic prompt.
Next, using function overloading, write a function that achieves
the same results.
*/
#include <iostream>
#include <string>
int askNumberFn(int number, std::string prompt = "Please enter a number, now: "); // default arguments must come last, in order of excecution
std::string askNumberFn(std::string prompt = "Please type a number, now: "); // default parameters must be different in order to overload Fn
char exitTimeFn();
int main()
{
askNumberFn("Please type a number: "); // We require the calling code to return a prompt
askNumberFn(); // We also require the Fn to return a default prompt
int number = 0;
number = askNumberFn(number, "Please enter a number: "); // To prove we have overloaded the FN, we require the Fn to also return an int
number = 0; // We return the value of number to zero, in order to remove any doubt, if we input the same number again
number = askNumberFn(number); // Lastly, we have to prove our overloaded Fn displays a default prompt
exitTimeFn();
return 0;
}
int askNumberFn(int number, std::string prompt)
{
std::cout << prompt;
std::cin >> number;
std::cout << "You entered the number: " << number << std::endl;
return number;
}
std::string askNumberFn(std::string prompt)
{
std::string word;
std::cout << prompt;
std::cin >> word;
std::cout << "You typed the number: " << word << std::endl;
return word;
}
char exitTimeFn()
{
char exitNow;
std::cout << "Press 'x' to exit: ";
std::cin >> exitNow;
return exitNow;
}
-
\$\begingroup\$ "Next, using function overloading, write a function that achieves the same results." Was this copied correctly? I haven't the first idea what they could be asking. \$\endgroup\$User319– User3192017年03月18日 01:41:47 +00:00Commented Mar 18, 2017 at 1:41
-
\$\begingroup\$ "Using default arguments, write a function that asks the user for a number and returns that number. The function should accept a string prompt from the calling code. If the caller doesn't supply a string for the prompt, the function should use a generic prompt. Next, using function overloading, write a function that achieves the same results." Yes, it is quoted from the source material. I reference it in my original question, and in my code. \$\endgroup\$paddyblack– paddyblack2017年03月18日 01:48:57 +00:00Commented Mar 18, 2017 at 1:48
1 Answer 1
Correctness: There are some cases that aren't handled. What happens if the user enters a word instead of a number? What if the user enters 2.1
? The program will exit regardless of what character the user enters when exitTimeFn()
is called.
I think your overload was a clever solution to a vague instruction. To make it clear that the extra parameter is irrelevant, you could comment out the name. For example:
int askNumberFn(int /*number*/, std::string prompt)
{
int number;
std::cout << prompt;
Because parameters are used to supply data to functions, it doesn't make sense to pass in a value, then immediately re-assign it before use.
Parameters: I would pass the strings by const reference instead of by value.
Naming: No need for Fn
at the end of every function. It's obvious that it's a function from how it's used. The names could also be slightly more descriptive: getNumberFromUser
, showExitDialogue
, for example.
Commenting: Generally, I'd discourage line-by-line comments explaining what each line of code is doing. It's usually a sign you need to write clearer code. The way you use it in your main
function to document your testing has some merit, I think. Look into unit testing for a more scalable/professional way of doing the same thing.
If accidentally using the same input for testing is a concern, I'd just use a different variable completely. A unit testing library would provide better tools to handle this.
While I believe this fulfils the question literally, there is an implied task of reacting reasonably to invalid input. I would test more thoroughly and make sure the edges don't do anything surprising.
-
\$\begingroup\$ What I'd like to achieve is a Fn that takes user input (ints, floats, strings...) and utilises the correct form of function on the fly. That, I think, is beyond this stage of the book, and my knowledge. Could you show me an example? Most important to me, at the very least, is if have I achieved what the exercise has asked of me? I take your points on line commenting, naming (was banging head against wall earlier, introduced these for clarity), and const string parameters. Lastly, how irrelevant is the /*number*/ parameter if I then have to declare it in the Fn definition? \$\endgroup\$paddyblack– paddyblack2017年03月18日 03:48:50 +00:00Commented Mar 18, 2017 at 3:48
-
1\$\begingroup\$ @PatrickCanney Templates can kind of do what you want. But if the user enters "1", you could store that as a string, or ant int, or a size_t, or a double, or lots of other things, so it can't really automatically figure out which one is correct for your program. I've edited my answer with answers to your other questions. \$\endgroup\$User319– User3192017年03月18日 04:17:14 +00:00Commented Mar 18, 2017 at 4:17