C++ input check - c++

I have this piece of code and it makes an input check. It works until some point but when I enter for example "12rc" which is supposed to be invalid the check is skipped. How can I change it? Thank you in advance!
cout << "Enter your choice 1, 2, 3: ";
cin >> choice;
cout << endl;
while (cin.fail() || choice <=0 || choice >=4) { // check input value
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Wrong input value! Please enter only 1, 2, 3: ";
cin >> choice;
cout << endl;

I give an assumption that you want to get an integer from the standard input stream. In other cases you may take the same idea and realize how to generalize your problem.
I think that it might be solved somehow like this
#include <iostream>
#include <cctype>
#include <stdexcept>
void skip_to_int() {
if (std::cin.fail()) {
// try to fix up a mess in the input
std::cin.clear();
for (char ch; std::cin >> ch; ) {
if (std::isdigit(ch) || ch == '-') {
std::cin.unget()
return;
}
}
}
// throw an error for example
throw std::invalid_argument{"Not integral input"};
}
int get_int() {
int n;
// try to get the integer number
while (true) {
if (std::cin >> n) {
return n;
}
std::cout << "Sorry, that was not a number. Try again" << std::endl;
// if user inputed not an integral try to search through stream for
// int occurence
skip_to_int();
}
}
int main() {
std::cout << "Enter your choice 1, 2, 3: " << std::endl;
int choice = get_int();
while (choice <= 0 && choice >= 3) {
// continue searching
choice = get_int();
}
// process choice somehow
}

There is nothing wrong with your code. It works fine for inputs like "12rc": http://ideone.com/Ma0j7r
The inputs:
12rc
0
a
11
$
10
2
Yield:
Enter your choice 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Wrong input value! Please enter only 1, 2, 3:
Is it possible that you had a space before the "2rc"? These inputs would be read as 1:
"1 2rc"
"1rc"
\n1\nrc"

Related

How to check for input validity? - C++

srand(time(0));
int rolls, x;
string input;
die *d;
die header1;
cout << "Please enter the number of dies to use (4, 5, or 6) or press enter to default to 6 dies: ";
getline(cin, input);
if (input.empty())
{
// 6 dies by default
x = 6;
}
else if (input != "4" && input != "5" && input != "6" && !(cin.get() == '\n'))
{
while (input != "4" && input != "5" && input != "6") {
cout << "INVALID Input: ";
getline(cin, input);
}
}
else
x = stoi(input);
I don't understand why the loop won't exit. The user should only input 4, 5, 6 and ENTER key for default value of 6. I checked for if they just hit ENTER key on first try but then if they hit something else like 2 or anything else, it'll say INVALID input. Inside the while loop though, as long as they enter 4,5,6 and ENTER key, it should exit right? Not only does it just keep cycling through but when i add the cin.get() condition to the while loop, it seems like it is even expecting user input before it re-iterates through the loop again. Am I using cin.get() wrong to check for user input emptiness?
The input could be rewritten to use an outer while loop that continues to loop until the input is acceptable. Then there is no need to use/misuse cin::get:
#include <iostream>
#include <string>
int main()
{
std::string input;
// loop until the input is good
while (true)
{
std::cout << "Please enter the number of dies to use (4, 5, or 6) or press enter to default to 6 dies: ";
std::getline(std::cin, input);
// something was entered
if (!input.empty())
{
// check for 4, 5, or 6 being entered
if (input == "4" || input == "5" || input == "6")
break; // get out of input loop
else
// input entered is no good
std::cout << "\nINVALID Input: " << input << ". Please try again:\n\n";
}
else // nothing was entered
{
input = "6";
break; // get out of input loop
}
}
std::cout << "\nSuccess: Your input was: " << input;
}
Live Example
Note that something like 4 will not be considered valid, since there is a trailing space. If you need to trim any excess space, that is another issue.

How can I throw a error if the user enters more than one integer

So this is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
long int iterFunc(int);
long int recurFunc(int);
int main() {
int n;
while(true){
try{
cout << "Enter: ";
if (!(cin >> n))
throw("Type Error");
if (n < 0)
throw n;
else
if (n == 0)
break;
cout << "Iterative: " << iterFunc(n) << endl;
cout << "Recursive: " << recurFunc(n) << endl;
}
catch(int n){
cout << "Error. Enter positive number." << endl;
}
catch(...){
cin.clear();
cin.ignore(100, '\n');
cout << "Error. Please enter a number" << endl;
}
}
cout << "Goodbye!";
return 0;
}
long int iterFunc(int n){
vector<long int> yVec = {1, 1, 1, 3, 5};
if (n <= 5)
return yVec[n - 1];
else
for(int i = 5;i < n; i++){
long int result = yVec[i - 1] + 3 * yVec[i- 5];
yVec.push_back(result);
}
return yVec.back();
}
long int recurFunc(int n){
switch (n) {
case 1:
case 2:
case 3:
return 1;
break;
case 4:
return 3;
break;
case 5:
return 5;
break;
default:
return recurFunc(n - 1) + 3 * recurFunc(n - 5);
break;
}
}`
The program shoud accept only one integer and return the y of the function using both iterative and recursive implemetations. Ex.: 30, 59, 433. How can I throw an error message if the user enters more then one integer, separated by space? Ex.: '3 45 32'.
I tried using if (cin.getline == ' ') throw("Error name") but the program still executes and return the y of the function for number in the input
Something like this works:
int main()
{
std::string str;
std::cout << "? : ";
std::getline(std::cin, str);
std::string::size_type pos(0);
int i = std::stoi(str, &pos);
if (pos != str.length())
return 1;
}
I found a part of my old code that might come in handy.
int val;
do
{
cin>>val;
if(!cin){ //you can add more conditions here
cin.clear();
cin.sync();
/* additional error handling */
}
else{
break; //input is correct - leaving loop
}
}while(true); //or here
Basically what !cin does is - it checks what type of value you actually want to write to, because it's needed anyway to figure out if data type is written to the correct type of our val. This means, that "30" or "433" etc. are integers (correct), "s" or "string" etc. are strings (or char*, correct me if I am wrong) (incorrect).
This also means, that "3 45 32" should be interpreted as string, which should result in another loop run.
Note: I didn't really test this code, so it might be completely wrong.
Edit: Okay now after some tests I realised this code needs some retweaking.
Firstly, "3 45 32" is not interpreted as string (now understandable). Instead, first number (before whitespace) is saved as an integer and all other numbers are stored in the buffer (next cin will be filled with it), which we can avoid using cin.clear() and cin.sync() once again.
The question is - is it okay for you to accept the first integer and ignore everything after the first whitespace? If not, you will have to save the input as string and extract whatever data you want from it.
I am leaving the original answer as is for simplicity of finding references in this edit.

Console is being flooded when error checking for things that are not an int

I'm trying to only allow integer values into my program, so I've made the following function. The function is similar to other ones I've seen online, and mine seems to work just fine up until I add an ! in front of it to check if something is not an int.
Function to check if input is an integer:
bool isInteger(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false)
{
return false;
}
return true;
}
}
Function being put to use:
int getLevel()
{
int level;
std::cout << "Level One\n";
std::cout << "Level Two\n";
std::cout << "Level Three\n";
std::cout << "Level Four\n";
std::cout << "Level Five\n";
std::cout << "Enter your level (1-5): ";
std::cin >> level;
while (!isInteger(std::to_string(level)) || level < 1 || level > 5)
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> level;
}
clrscr();
return level;;
}
I believe the function works just fine until I put the ! in front of it. I am trying to only allow integer input into my program, and when I enter a double or string, the console becomes flooded with the message "Enter an integer value between 1-5 inclusive: " and doesn't give any time to enter an input. I am fairly new to c++ programming and could use some advice. Thank you!
std::cin >> level;
will try to read an integer and it will never read anything other than an integer. If this fails std::cin's failbit is set and further input operations (like std::cin >> level; inside the loop) are skipped.
You need to check if the reading succeeded and ignore the current input if not. Like this for example:
std::cout << "Enter your level (1-5): ";
while(!(std::cin >> level) || level < 1 || level > 5) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter an integer value between 1-5 inclusive: ";
}
As little semi-related hint: level will always be an integer. Converting it to a string will always be the string-representation of an integer, so isInteger(std::to_string(level)) will always be true, unless level is negative, because you don't check for the sign.
Also that return true; in isInteger must be outside the loop, else you only check the first character.
Thanks to all the replies and clarification, I've managed to come up with a solution of my own.
New isInteger function that now checks for everything that is needed including inputs like "0004" that a user suggested above:
bool errorCheck(std::string s)
{
int intLevel;
std::stringstream tempLvl(s);
tempLvl >> intLevel;
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false || s[0] == '0' || intLevel < 1 || intLevel > 5)
{
return false;
}
}
return true;
}
The method in action:
std::cout << "Enter your level (1-5): ";
std::cin >> stringLevel;
while (!errorCheck(stringLevel))
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> stringLevel;
}
std::stringstream lvl(stringLevel);
lvl >> level;
clrscr();
return level;
}
Please let me know if you spot any problems with the code or have any easier solutions. Thanks for all the help!
ok i am gonna tell u the fact that console input extracts the input from console so if u ever tried to do something like that
i.e read string in place of integer the cin is going to be in bad state you can check this fact by putting an if like this
if(!cin>>level) break;
and u will find it working actually stream takes input from the console and convert it to boolean value so u can always check it's state bad state return false else true...... ..
SO,finally the bug is in cin>>level...
I hope u understood.... also check out that return true statement..
i am gonna put u reference link for more answer on this bug...
user enters String instead of Int

C++ Switch loop error

I'm a C++ beginner. My problem is, if the user accidentally inputs a letter, the program will send the error message and it wont loop back. This is my code:
#include <string>
#include <iostream>
using namespace std;
int main()
{
int q;
A:
cout << "[1] Name";
cout << "\n[2] Address";
cout << "\nEnter your choice: ";
cin >> q;
switch (q)
{
case 1:
cout << "XXXXXXXXXX" << endl;
break;
case 2:
cout << "XXXXXXXXXX" << endl;
break;
default:
cout << "Error! Enter only numbers from 1 - 2" << endl;
goto A;
}
return 0;
}
Output was :
[1] Name
[2] Address
Enter your choice: x
Error! Enter only numbers from 1 - 2
[1] Name
[2] Address
Enter your choice: Error! Enter only numbers from 1 - 2
[1] Name
[2] Address
Enter your choice: Error! Enter only numbers from 1 - 2
...
It should be like this,
[1] Name
[2] Address
Enter your choice: 8
Error! Enter only numbers from 1 - 2
[1] Name
[2] Address
Enter your choice:
If user enters a wrong number, it loops back, and if the user enters a letter, it should loop back like this too.
What is wrong?
The problem is that when you enter a non-integer input, the input is not actually extracted from the input-buffer, so each iteration of the loop you will attempt to read the same input over and over again.
What you need to do is rely on the fact that illegal input (non-integer in your case) will cause the stream to set its failbit, that the input operator >> function returns a reference to the stream, and that the state of a stream can be checked in a simple boolean condition.
Something like
if (std::cin >> q)
{
// Successfully read an integer
}
else
{
// Failed to read an integer, input is probably something else
// Clear the failbit
std::cin.clear();
// Explicitly ignore the rest of the line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Output error message
}
The above code can be put in a loop that is exited by setting a boolean variable in the switch-cases for valid integers.
References:
std::ios::clear
std::istream::ignore.
std::numeric_limits
Since the input might not be numeric, let's allow for that. I'm assuming the use of System.String -- if it isn't, modifying this snippet is left as an exercise for the student.
using System;
String entry = "";
int entry_val = 0;
bool valid = false;
do
{
//menu goes here
cin >> entry;
if ( entry >= "1" && entry <= "2" )
{
entry_val = entry.ToInt();
valid = true;
}
else
{
cout << "Error! Enter only numbers from 1 - 2" << endl;
}
while (valid == false)
...
continue with the switch() {} block.

C++ input not being read

I just started with c++ (coming from java) and I'm trying to do some basic exercises. The idea is to ask for any input other than 5, if the user inputs 5, display a message, and if the user inputs anything other than 5 ten times, display another message. Here's the code:
void notFive () {
int count = 0;
while (count < 10) {
int input = 0;
cout << "Enter any number other than 5." << endl;
cin >> input;
if (input == 5)
break;
count++;
}
if (count == 10)
cout<<"You are more patient than I am, you win.";
else
cout << "You weren't supposed to enter 5!";
}
}
My problem is that all this code does is print out "Enter any number other than 5." 10 times, then say "You are more patient that I am, you win." any ideas what is wrong?
if you guys want all my code (to make sure I'm not just being an idiot) here it is:
#include <iostream>
#include <stdio.h>
using namespace std;
class Hello {
public:
void notFive () {
int count = 0;
while (count < 10) {
int input = 0;
cout << "Enter any number other than 5." << endl;
if ( ! (cin >> input) ) {
cout << "std::cin is in a bad state! Aborting!" << endl;
return;
}
if (input == 5)
break;
count++;
}
if (count == 10)
cout<<"You are more patient than I am, you win.";
else
cout << "You weren't supposed to enter 5!";
}
}hello;
int main() {
Hello h;
h.notFive();
return 0;
}
Your code works perfectly for me (in Visual Studio 2012) when I change notFive to main. Your problem must lie outside this code (possibly because cin is in a broken state, as others have suggested).
Change this line:
cin >> input
To this:
if ( ! (cin >> input) ) {
cout << "std::cin is in a bad state! Aborting!" << endl;
return;
}
The behavior you describe is what would happen if Something Bad happened to cin before this code was run.
Edit:
Add this same code to earlier uses of cin to find out where it's entering a bad state.
An example of this happening would be if the code tried to read an int, and the user typed a letter of the alphabet.
You can also call cin.clear(); to restore the working state of cin.
Here are my comments:
fflush(stdin) is not valid. The stdin cannot be flushed. Also,
this may not be the same input as cin.
You need to check for cin.fail after cin >> input. If I enter a
letter, your input statement will fail.