Hello I'm relatively new to operator overloading, but I do believe its the answer to a problem i've been facing in almost every program I make. My goal is to overload std::cin >> int_var so that it can only accept integer inputs, and if it detects that an input besides a int was entered it puts the user into a loop until the input is an int.
This is what I've came u with so far
#include <iostream>
std::istream& operator>> (std::istream& Cin, int *var)
{
int var2;
if(!Cin >> var2)
{
std::cout << "Invalid input!";
}
return Cin;
}
int main() {
int var;
std::cin >> var;
std::cout << var;
}
Note: This code snippet is just to see if I can detect an invaild input. It don't need it to include the loop just yet.
CodePudding user response:
The correct way to get user input is to:
- read a string
- attempt to convert the string to int (or whatever)
- if the conversion fails, you should either:
- ask and try again, only IFF user is known to be a human
- terminate (require your users to give valid inputs)
This is because the user will always press Enter after every input prompt.
Variations on this question abound. Here’s my last answer, complete with a working example.
CodePudding user response:
I don't know if you can. What you need to do is validate any and all user input. No matter what the application is never trust the user.
So you just need to check if the value you get is an integer then you can call your function and if it isn't a integer then ask for the input again and tell them why it was wrong like "Input only accepts integers".
CodePudding user response:
I don't recommend that you attempt to overload the stream extraction operator >> in order to significantly change its behavior. It would make more sense to create your own function.
The stream extraction will accept user input such as "6sdfj23jlj" as valid input for the number 6. If you instead want to reject such input and reprompt the user for new input in such a case, then it would probably make more sense to use line-oriented input such as std::getline, instead of the stream extraction operator >>.
After reading in a string with std::getline, you can attempt to convert it to an integer using the function std::stoi.
In the following program, I have created a function get_int_from_user, which will repeatedly ask the user for input, until the input is valid.
#include <iostream>
#include <string>
int get_int_from_user( const std::string& prompt )
{
std::string line;
std::size_t pos;
int i;
//repeat forever, until an explicit return statement or an
//exception is thrown
for (;;) //equivalent to while(1)
{
//prompt user for input
std::cout << prompt;
//attempt to read one line of input from user
if ( !std::getline( std::cin, line ) )
{
throw std::runtime_error( "unexpected input error!\n" );
}
//attempt to convert string to integer
try
{
i = std::stoi( line, &pos );
}
catch ( std::invalid_argument& )
{
std::cout << "Unable to convert input to number, try again!\n";
continue;
}
catch ( std::out_of_range& )
{
std::cout << "Out of range error, try again!\n";
continue;
}
//The remainder of the line is only allowed to contain
//whitespace characters. The presence of any other
//characters should cause the entire input to get rejected.
//That way, input such as "6sdfj23jlj" will get rejected,
//but input with trailing whitespace will still be accepted
//(just like input with leading whitespace is accepted by
//the function std::stoi).
for ( ; pos < line.length(); pos )
{
if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )
{
std::cout << "Invalid character found, try again!\n";
//we cannot use "continue" here, because that would
//continue to the next iteration of the innermost
//loop, but we want to continue to the next iteration
//of the outer loop
goto continue_outer_loop;
}
}
//input is valid
return i;
continue_outer_loop:
continue;
}
}
int main()
{
try
{
int i = get_int_from_user( "Please enter a number: " );
std::cout << "Input was ok, you entered: " << i << '\n';
}
catch ( std::runtime_error& e )
{
std::cout << "Runtime error:" << e.what() << '\n';
}
}
This program has the following behavior:
Please enter a number: Test
Unable to convert input to number, try again!
Please enter a number: 3000000000
Out of range error, try again!
Please enter a number: 6sdfj23jlj
Invalid character found, try again!
Please enter a number: 633245183
Input was ok, you entered: 633245183
The code above uses one goto statement. Normally, you should not use goto if possible, but for breaking out of nested loops, it is considered appropriate.
