I have 3 cin for ints.
int input1;
cin >> input;
int input2;
cin >> input2;
int input3
cin >> input3;
The problem is if i type 2 3 4 in console, it will input all 3 in one shot. How can i prevent this? And possibly give them a warning if they do this. basically error input validating.
One possible solution:
int strict_stoi(const string& s)
{
size_t end_pos;
int num = stoi(s, &end_pos);
for (size_t i=end_pos; i<s.length(); ++i)
{
if (!isspace(s[i]))
throw invalid_argument("You have entered some garbage after the number!");
}
return num;
}
int read_number()
{
string s;
getline(cin, s);
return strict_stoi(s);
}
int read_number_with_retry(const char* prompt)
{
for (;;)
{
try
{
cout << prompt;
return read_number();
}
catch (invalid_argument& ex)
{
cout << ex.what() << endl;
}
}
}
int test()
{
int input1 = read_number_with_retry("Enter input #1: ");
int input2 = read_number_with_retry("Enter input #2: ");
int input3 = read_number_with_retry("Enter input #3: ");
return 0;
}
If you enter a totally invalid argument (for example "a") then it will show you a not too user friendly "invalid stoi argument" message but if you enter "5 6" then it shows "You have entered some garbage after the number!". If you want to replace the "invalid stoi argument" message with something user friendly then instead of throwing an invalid_argument exception when you find "garbage after the number" you should throw you own garbage_after_the_number exception and in this case you could make the distinction between two different errors: invalid_argument would be thrown only in case of invalid inputs (like "a") and garbage_after_the_number would be thrown only in case of the other kind of error so you would be able to catch two different exceptions and you could print totally customized message in these two cases. I leave the implementation of this to you as an extra exercise.
You may do:
#include <iostream>
#include <sstream>
int main() {
while(true) {
std::cout << "Enter a number [Enter to quit]: ";
std::string line;
getline(std::cin, line);
if(line.empty()) break;
else {
std::stringstream input(line);
int number;
// Preceding white space number trailing white space:
input >> number >> std::ws;
if(input && input.eof()) {
std::cout
<< "The number surronded by possible white space is: "
<< number
<< '\n';
}
else {
std::cout
<< "The input line is invalid: "
<< line
<< '\n';
}
}
}
}
And if you want to be strict:
#include <iostream>
#include <iomanip>
#include <sstream>
...
// Number without preceding and trailing white space:
input >> std::noskipws >> number;
...
Related
Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
I'm working on a small program for school to compute a factorial of an inputted number. I've got a good amount of experience in Java, but this is my first go at C++.
My problem: I need to be able to have a single input from the user, which is either an integer or the character 'q', which signifies the application needs to quit.
Here is my current attempt:
#include <stdio.h>
#include <iostream>
#include "Header.h"
using namespace std;
int x=0;
char y;
int main(int argc, char *argv[])
{
printf("Hello, please enter a number to compute a factorial (or 'q' to quit): ");
cin >> y;
x= (y-'0');
if(y=='q')
{ printf("Thanks for playing!\n");
exit(1);
}
long result= print_Factorial(x);
cout << x << "!= " << result << "\n";
return result;
}
This casting does not work, however. If I enter a double digit number, such as 12, it only converts to x the first digit of the two and computes that factorial. I'm sure this is simple, what am I missing?
Explicit answer or a lead to where I can learn more about this problem, anything is appreciated.
There are functions you can use to try and covert a string into a number, and which you can check if the conversion was a success or not. The std::strtol function is one of them:
std::string input;
std::cin >> input;
char* endptr = nullptr;
const char *input_ptr = input.c_str();
long value = std::strtol(input_ptr, &endptr, 10);
if (endptr == input_ptr)
{
// Input was not a valid number
}
else if (*endptr != '\0')
{
// Input starts with a valid number, but ends with some extra characters
// (for example "123abc")
// `value` is set to the numeric part of the string
}
else
{
// Input was a valid number
}
If you don't mind exceptions, then you can use e.g. std::stoi instead:
std::string input;
std::cin >> input;
int value = 0;
try
{
size_t endpos = 0;
value = std::stoi(input, &endpos);
if (endpos != input.length())
{
// Input starts with a valid number, but ends with some extra characters
// (for example "123abc")
// `value` is set to the numeric part of the string
}
else
{
// Input is a valid number
}
}
catch (std::invalid_argument&)
{
// Input not a valid number
}
catch (std::out_of_range&)
{
// Input is a valid number, but to big to fit in an `int`
}
The reason you're getting the first digit is because you're using
cin >> y; where y is a char, which holds one character. So you're only getting one character.
What you probably would want to do is get the answer as a string, and once you check that the string is not == "q", then you could convert it to an int.
#include <iostream>
#include <sstream>
int main() {
std::string in;
std::cout << "Please enter a digit: ";
while(std::cin >> in) {
std::cout << "Input: " << in << std::endl;
if(in.size() == 1) {
if(in[0] == 'q' || in[0] == 'Q') {
std::cout << "Quit" << std::endl;
return 0;
}
}
std::istringstream parse(in);
int value;
if(parse >> value) {
if(parse.eof()) {
std::cout << "Success" << std::endl;
return 0;
}
}
std::cout << "Please try again: ";
}
std::cerr << "This should not happen <control + d>" << std::endl;
return 1;
}
Your user can enter whatever line of text, you you have to read a "line of text" to validate.
#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
std::string text;
std::getline(std::cin,text);
if(text.size()==1 && text[0]=='q')
{
std::cout << "quit command";
return 0;
}
try
{
int i = std::stoi(text); //may throw if text is not convertible
/* whatever elaboration and output */
return 0;
}
catch(const std::exception& e)
{
std::cout << "bad input: " << text << '\n';
std::cout << "caused excpetion: " << e.what() << std::endl;
}
return 3; //means "excpetion thorown"
}
Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}