How can I restrict the user to input real numbers only in C++ program?
Example:
double number;
cin >> number;
and it won't accept the input like: '12add' , 'abcd' etc...
can someone guides me to that? using bool value.
Thanks!
You cannot force the user to give correct input. But you can ask them to give another input if previous was invalid. There are different procedures to do so. One is the following:
Use getline to read a line
Parse and understand the line
If line is invalid, give error to user and go to 1
This is alright and quite common. It uses dynamic memory though. Another option would be:
Use cin >> value; like you normally do
Check cin.fail() to see if input was correctly read (check for cin.eof() also)
If failed, ignore all input until whitespace:
char c;
while (cin >> c)
if (isspace(c))
break;
This has the added advantage that in an erroneous input like this:
abc 12.14
you don't ignore the whole line, but just the abc.
I always use this code to request a specific type of input(Except strings and chars).
The idea is to request any numeric type and use stringstream to see if it can be stored as the requested type, if not it will keep prompting the user until he inputs the requested type.
template <typename T> // will not work with strings or chars
T forceInputType_T() {
T name;
bool check = false;
string temp;
while (check == false) {
cin >> temp;
stringstream stream(temp);
if (stream >> number) {
check = true;
} else {
cout << "Invalid input type, try again..." << endl;
}
}
return name;
}
If you want to use a Boolean then you could check every character in the string if it contains a number than return false and keep asking for an valid input with a loop !
You cannot restrict what user types on the keyboard. You can accept it as std::string and use boost::lexical_cast to convert it to your expected number type and catch and process boost::bad_lexical_cast exception.
You can retrieve your data as a std::string then use one of the standard string conversion function to see if the content matches your expectations.
double number
if (cin >> number) {
do_stuff_with(number);
} else {
std::cerr << "That wasn't a number!";
}
Check out the sscanf function.
Unfortunately you cannot avoid it... You can accept a string as input and parse the string (maybe with regex) for correctness.
You can use regex to solve it
double inputNumber()
{
string str;
regex regex_double("-?[0-9]+.?[0-9]+");
do
{
cout << "Input a positive number: ";
cin >> str;
}while(!regex_match(str,regex_double));
return stod(str);
}
Remember that include regex library in the header.
Use this:
#include <conio.h>
#include <string>
#include <iostream>
using namespace std;
int main() {
cout << "Input a positive whole integer: ";
string currentInput;
while (true) {
char ch = getch();
if (ch <= '9' and ch >= '0') cout << ch; currentInput += ch;
// Handle other keys (like backspace, etc)
else if (ch == '\r') cout << endl; break;
}
}
Related
In my case, I have to make sure the user input is either 1 or 2, or 3.
Here's my code:
#include <iostream>
using namespace std;
void invalid_choice_prompt() {
string msg = "\nInvalid Command! Please try again.";
cout << msg << endl;
}
int ask_user_rps_check_input(int user_choice) {
if (user_choice == 1 || user_choice == 2 || user_choice == 3) return 1;
return 0;
}
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}
int main() {
ask_user_rps();
return 0;
}
The code is capable to handle the situation when the input is an integer, but when the input are characters or strings, the program will be trapped in the infinite loop.
Is there any elegant way to do this? I've found some methods about using cin.ignore to ignore the specified length of io buffer, but I don't think this method is flexible enough. I am looking for a more flexible solution.
I think an option would be to collect the user input to a string and then move it to stringstream using getline kind of like this:
std::string input;
std::getline(std::cin, input);
//Now check if the input is correct. if it is, then:
std::stringstream stream;
stream << input;
int num;
stream >> num;
I'm not sure if this is a good method but it works.
One of the simplest solution would be to check the cin stream failure something like below:
int ask_user_rps() {
// ask user's choice of Rock or Paper or Scissors
while (1) {
string msg =
"\nPlease enter your choice:\nRock - 1\nPaper - 2\nScissors - 3";
cout << msg << endl;
int user_choice;
cin >> user_choice;
if(cin.fail()) {
invalid_choice_prompt();
std::cin.clear();
std::cin.ignore(256,'\n');
continue;
}
if (ask_user_rps_check_input(user_choice)) {
return user_choice;
}
invalid_choice_prompt();
}
}
Reading from a stream using operator >> takes as many characters from the stream as the target type accepts; the rest will remain in the stream for subsequent reads. If the input has a format error (e.g. a leading alphabetical characters when an integer is expected), then an error-flag is set, too. This error-flag can be checked with cin.fail(). It remains set until it gets explicitly cleared. So if your code is...
int user_choice;
cin >> user_choice;
and if you then enter something that is not a number, e.g. asdf, then user_choice has an undefined value, an error-flag cin.fail() is (and reamins) set. So any subsequent read will fail, too.
To overcome this, you have to do three things:
First, check the error-flag. You can do this either through calling cin.fail() after a read attempt of through checking the return value of the expression (cin >> user_choice), which is the same as calling cin.fail().
Second, in case of an error, you need to clear the error-flag using cin.clear(). Otherwise, any attempt to read in anything afterwards will fail.
Third, if you want to continue with reading integral values, you need to take the invalid characters from the stream. Otherwise, you will read in asdf into a variable of type integer again and again, and it will fail again and again. You can use cin.ignore(numeric_limits<streamsize>::max(),'\n'); to take all characters until EOF or an end-of-line from the input buffer.
The complete code for reading an integral value with error-handling could look as follows:
int readNumber() {
int result;
while (!(cin >> result)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Input is not a number." << std::endl;
}
return result;
}
Take input as char
string user_choice;
cin >> user_choice;
check input is valid or not if(user_choice=='1')
I thought I understood handling bad input with cin.clear() and cin.ignore(), like it is explained here, but in the following example
#include <iostream>
#include <limits>
using namespace std; //I know that this isn't good practice.
int main () {
int a, b;
while (cout << "Input some int: " && !(cin >> a)) {
cout << "Wrong datatype!\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
while (cout << "Input some int: " && !(cin >> b)) {
cout << "Wrong datatype!\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
if (a > 1) cout << "Some event.\n";
if (b > 1) cout << "Some other event.\n";
return 0;
}
the behavior I want is only present when the unwanted input is some character.
So if I enter x and y, I will again be asked for two ints and get the appropriate outputs, same if I enter a char and an int two times.
However: If I input, say, 2.3, I will get
Input some int: Wrong datatype!
but won't have a chance to correct my input, since the result invariantly outputs "Some event." The second prompt just accepts the float right away.
What's happening, actually, is the 2 in 2.3 is being accepted by the first prompt, leaving .3 in the input buffer. The Wrong datatype! you are seeing is from your second prompt, seeing a ., which is not a valid character for an integer. You then, I assume, enter an integer which is accepted by your second prompt.
This fundamental approach is fragile, and error-prone.
Your obvious intent is to accept a line of input, and process it. If so, then the correct function to do that is std::getline(). That's what its purpose is. That's exactly what it does. The >> operator does not do that. That's not what it's for. Of course, by using the various auxiliary methods, like ignore(), and clear(), one can still achieve that goal, but, as you've discovered, using those functions correctly is not intuitive. Of course, you can spend copious time pouring over their documentation to understand their every semantic behavior, but why bother, when you can simply use std::getline(), and then move on to something else. It's simply easier to do that.
Of course, once a line of input is received, you would like to parse it into an integer. Now is the correct time to use >> to parse it:
std::string line;
if (std::getline(line, std::cin))
{
std::istringstream i{line};
int n;
if (i >> n)
{
// Input parsed
}
}
Isn't this simpler, more straightforward, and less of a gotcha?. Of course, entering "2.3" here will result in the >> operator parsing the "2", and succeeding, leaving ".3" unparsed. If you would like to detect this situation, simply use get() to see what's left in the std::istringstream. Perhaps accept any trailing whitespace, if you wish.
The problem here is when you enter something like 2.3 to a int cin is okay with that. It reads the 2, sees the . so it stops reading and stores the 2 in the variable and leaves the .3 in the buffer for the next call. So, you pass the first loop, get to the second loop, and then you fail as it tries to read in the . into b. Then you clear the .3 and you can enter another input. If you enter another 2.3 the same thing will happen and b will get 2 and the program continues on.
The "bullet proof" way to read in input is to read it in as a std::string and then parse that to make sure the full input was good. That would look like
std::string line;
while (cout << "Input some int: " && std::getline(cin, line)) {
std::stringstream ss(line);
ss >> a;
if (ss.eof()) // we did consume all the input
break;
else
cout << "Wrong datatype!\n";
}
while (cout << "Input some int: " && std::getline(cin, line)) {
std::stringstream ss(line);
ss >> b;
if (ss.eof()) // we did consume all the input
break;
else
cout << "Wrong datatype!\n";
}
When you input "2.3", cin will stop at '.', and interpret '2' as the desired input.
Then, you will clear cin, when the '.' is encountered, discarding 3.
If you then input a new integer, it will accept it.
Many answers here suggest the use of std::getline and string parsing, either using the string functions or stringstreams. This is quite inefficient and not the way the streams are supposed to be used.
Instead, parse the data when it is still in the input stream:
#include <iostream>
#include <cctype>
#include <limits>
struct read_int {
int& a;
read_int(int& aa) : a{ aa } { }
friend std::istream& operator >>(std::istream& is, read_int& ri) {
char delim;
while(!(is >> ri.a) || (delim = is.get(), delim != '\n' && !std::isspace(delim))) {
std::cerr << "Bad!\n";
is.clear();
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return is;
}
};
int main() {
int a, b;
std::cin >> read_int(a) >> read_int(b);
std::cout << a << ' ' << b;
return 0;
}
This function will accept input like "4 5" or "4\n6" alike, but requests a new input for data like "4.2", discarding everything read before.
This function keeps getting called in another function inside a while-loop while valid_office_num is false. The problem is that if the input begins with a digit but is followed by other invalid characters (e.g. 5t) it takes the digit part and accepts that as a valid input. I want it to consider the whole input and reject it so it can ask for another one. I thought I could use getline() but then I cannot use cin.fail(). How could I implement this behavior?
I forgot to mention I am very new to C++, I have only learnt the basics so far.
(To be clear the desired behavior is to reject anything that contains anything other than digits. This is not an integer range check question. If it is NOT an integer, discard it and request another one)
//Function to read a valid office number, entered by user
int read_office_num()
{
//Declaration of a local variable
int office_num;
//Read input
cin >> office_num;
//Check if input was valid
if (cin.fail())
{
//Print error message
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
//Clear error flags
cin.clear();
//Ignore any whitespace left on input stream by cin
cin.ignore(256, '\n');
}
else
{
//Office number entered is valid
valid_office_num = true;
}
return office_num;
}
From what I gather you want the whole line to be read as a number and fail otherwise?
Well, you can use std::getline(), but you have to follow the algorithm below (I will leave the implementation to you..)
use std::getline(cin, str) to read a line, and if this returns true
use std::stoi(str, &pos) to convert to integer and get the position of the last integer
if pos != str.size() then the whole line in not an integer (or if the above throws an exception), then it's not a valid integer, else return the value...
Read a line of input as a std::string using std::getline().
Examine the string and check if it contains any characters that are not digits.
If the string only contains digits, use a std::istringstream to read an integer from the string. Otherwise report a failure, or take whatever other recovery action is needed (e.g. discard the whole string and return to read another one).
You could use a stringstream
int read_office_num()
{
//Declaration of a local variable
int office_num;
string input = "";
while (true) {
getline(cin, input);
stringstream myStream(input);
if (myStream >> office_num)
break;
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n" << endl;
}
return office_num;
}
If you want to reject input like 123 xxx you could add an additional check to verify that the received string is indeed an integer:
bool is_number(const string& s)
{
string::const_iterator itr = s.begin();
while (itr != s.end() && isdigit(*itr)) ++itr;
return !s.empty() && itr == s.end();
}
int read_office_num()
{
//Declaration of a local variable
int office_num;
string input = "";
while (true) {
getline(cin, input);
stringstream myStream(input);
if (is_number(input) && myStream >> office_num)
break;
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n" << endl;
}
return office_num;
}
You should probably just look at the number of input characters that are left in cin. You can do that with in_avail
Your function will probably end up having a body something like this:
//Declaration of a local variable
int office_num;
//Read input and check if input was valid
for (cin >> office_num; cin.rdbuf()->in_avail() > 1; cin >> office_num){
//Print error message
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
//Ignore any whitespace left on input stream by cin
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
//Office number entered is valid
valid_office_num = true;
return office_num;
Points of interest:
There is always at least 1 character in cin otherwise the cin would be marked as bad and that would not be good
You don't need valid_office_num if read_office_num is implemented this way, cause valid_office_num will always be set to true before returning
Hm. I may be missing something, but why not read a line, trim it, use regular expressions to validate a number and then exploit strstream's facilities or just atoi if you must? In all reality I'd probably just let users get away with extraneous input (but discard it if I'm sure I'm always running interactively). Following the motto "be lenient in what you accept."
The "interactive" caveat is important though. One can generally not assume that cin is a terminal. Somebody may get cocky and let your program run on a text file or in a pipeline, and then it would fail. A robust approach would separate data processing (portable) from means of input (possibly machine specific and therefore also more powerful and helpful than stdin/stdout via a console).
Here's how to do it using Boost Lexical Cast:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <vector>
#include <string>
int read_office_num()
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
using namespace std;
int office_num;
while (true)
{
try
{
string input = cin.getline();
office_num = lexical_cast<int>(*argv));
break;
}
catch(const& bad_lexical_cast)
{
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
}
}
return office_num;
}
Ok, I'm trying to get good at using pointers so I'm trying to write a input validation for the user input to make sure that anything that isn't a number is handled correctly. When I use isdigit() isn't working for me. I still get an exception when I enter a alphabet. Any suggestions? Thanks. Check this out:
#include<iostream>
#include<algorithm>
#include<string>
#include<cctype>
using namespace std;
void EnterNumbers(int * , int);
int main()
{
int input = 0;
int *myArray;
cout << "Please enter the number of test scores\n\n";
cin >> input;
//Allocate Array
myArray = new int[input];
EnterNumbers(myArray,input);
delete[] myArray;
return 0;
}
void EnterNumbers(int *arr, int input)
{
for(int count = 0; count < input; count++)
{
cout << "\n\n Enter Grade Number " << count + 1 << "\t";
cin >> arr[count];
if(!isdigit(arr[count]))
{
cout << "Not a number";
}
}
}
If you test if (!(cin >> arr[count])) ... instead - isdigit(arr[digit]) tests if the value of arr[digit] is the ASCII code of a digit [or possibly matches Japanese, Chinese or Arabic (that is, as an Arabic script typeface, not that it's a 0-9 like our "Arabic" ones) digit]. So if you type in 48 to 57, it will say it's OK, but if you type 6 or 345, it's complaining that it is not a digit...
Once you have discovered a non-digit, you will also need to either exit or clean out the input buffer from "garbage". cin.ignore(1000, '\n'); will read up to the next newline or a 1000 characters, whichever happens first. Could get annoying if someone has typed in a million digits, but otherwise, should solve the problem.
You will of course also need a loop to read the number again, until a valid number is entered.
The way I do this kind of input validation is that I use std::getline(std::cin, str) to get the whole line of input and then I parse it using the following code:
std::istringstream iss(str);
std::string word;
// Read a single "word" out of the input line.
if (! (iss >> word))
return false;
// Following extraction of a character should fail
// because there should only be a single "word".
char ch;
if (iss >> ch)
return false;
// Try to interpret the "word" as a number.
// Seek back to the start of stream.
iss.clear ();
iss.seekg (0);
assert (iss);
// Extract value.
long lval;
iss >> lval;
// The extraction should be successful and
// following extraction of a characters should fail.
result = !! iss && ! (iss >> ch);
// When the extraction was a success then result is true.
return result;
isdigit() applies to char not to int as you're trying. The cin >> arr[count]; statement already ensures an integer numeric digits format is given in the input. Check cin.good() (!cin respectively) for possible input parsing errors.
I'd like to know how to limit an input value to signed decimals using std::cin.
double i;
//Reading the value
cin >> i;
//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}
This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.
If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:
int someVal;
while(!(cin >> someVal)) {
cin.reset();
cout << "Invalid value, try again.";
}
Combining the techniques from the top answer here and this website, I get
input.h
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
Sample run
Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.
cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.
I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.
Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:
#include <iostream>
#include <cstdlib>
// #arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
using namespace std; // *1
while(true)
{
cout << prompt;
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp)
return ret;
}
}
*1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
Something like:
double a;
cin >> a;
Should read your signed "decimal" fine.
You'll need a loop and some code to make sure it handles invalid input in a sensible way.
Good luck!