Problem with input in c++ - c++

I have a very basic question i want to take integer input in certain range from user. if the user gives some string or char instead of integer. then my program goes to infinite loop.
my code is some what like that
cin >> intInput;
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
cin >> intInput;
}
I am only allowed to use c++ libraries not the c libraries.

As mentioned in the possible duplicate, you should check the state of cin on each loop.
Possible implementation:
if(cin >> intInput)
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
if(!(cin >> intInput)){ break; }
}
Very ugly code, just trying to illuminate the answer which is to check the state of cin.

The solution to this answer is to always read lines from the standard input.
std::string input; int value = 0;
do
{
// read the user's input. they typed a line, read a line.
if ( !std::getline(std::cin,input) )
{
// could not read input, handle error!
}
// attemp conversion of input to integer.
std::istringstream parser(input);
if ( !(parser >> value) )
{
// input wasn't an integer, it's OK, we'll keep looping!
}
}
// start over
while ((value > 4) || (value < 1));

#include <locale>
..
if(!isalpha(intInput)) {
..
}
Note, this won't work if, for example the user enters a "+" but maybe it will put you in the right direction..

Related

How to ignore wrong cin input in C++?

This is code for a 4x4 tic-tac-toe game. I am new to programming. I don't know how to ignore wrong input from the user. I tried searching Google, I found cin.clear() and cin.ignore(). They did work a little bit, but not fully working. For example, if the user enters 11111111 4 o as input, the program exits instead of ignoring this. How to ignore this input?
And what are cin.clear() and cin.ignore() doing?
char game[4][4];
int r, c;
char ans;
cin >> r >> c >> ans;
--r, --c;
if (!check_ok(r, c, ans)){
cout << "try again: select available ones only!!!\n";
--count;//count checks for 16 turns through while loop
}else{
game[r][c] = ans;
++count1;
}
bool Game::check_ok(int a, int b, char an) {
if (game[a][b] == ' ' && a < 4 && b < 4 && ((count1 % 2 == 0 && an == 'x') || (count1 % 2 != 0 && an == 'o'))){
game[a][b] = an;
return true;
}
else{
cin.clear();
cin.ignore();
return false;
}
}
OK. User input is hard.
Interactive user input is line based.
User inputs some values and then hits return. This flushes the stream and unblocks the readers to get the value from the stream. So you should design your input code to be line based.
The first question seems to be is all the input on one line or do they input the values with a return between each? You can determine this with some outut to the user then follow the rules defined by your instructions.
So lets do a line based input example:
do {
// Your instructions can be better.
std::cout << "Input: Row Col Answer <enter>\n";
// Read the user input. 1 Line of text.
std::string line;
std::getline(std::cin, line);
// convert user input into a seprate stream
// See if we can correctly parse it.
std::stringstream linestream(std::move(line));
// Notice we check if the read worked.
// and that the check_ok() returns true.
// No point in call check_ok() if the read failed.
if (linestream >> r >> c >> ans && check_ok(r, c, ans)) {
break;
}
std::cout << "Invalid Input. Please try again\n";
}
while(true);
i think instead of ignoring the wrong input you should limit the users input into the ideal inputs only. maybe an if statement could help
if(input != ideal_input)
{
cout>>"invalid input";
}
else
{
//progress in the game
}

While condition: How to allow comparison between non-integer/double user input and integer limits

Objective: Run a while loop that will repeat until the user inputs an integer between 1-3 (inclusive). So if an integer that is smaller than 1 or bigger than 3 is inputted or any character or string is inputted, the loop repeats.
My noob knowledge: I know how to compare user input when it is an integer, but when it is a char or string datatype input all I get is an infinite loop. Plus I declared the inputtable variable as an integer, so not sure how to go on about this.
I've done some Google searches but can't seem to find a question similar enough to mine.
Advice is highly appreciated :)
Code below:
int Decision1 = 4;
while ( Decision1 < 1 || Decision > 3)
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << "\n\n";
}
int Decision1;
while(std::cin >> Decision1) {
if(Decision1 >= 1 && Decision1 <= 3) break;
// todo
}
You can use ASCII codes for checking number or character.
#include <iostream>
int main() {
char Decision1 = '0';
while ( (Decision1 < 49 && Decision1 >=47) || (Decision1 >51 && Decision1 <=57 ))
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << Decision1;
std::cout << "\n";
}
}
I hope helpful for you.
Keep in mind: when you read input from std::cin you're reading text that's typed at the console. The stream extractor tries to convert that text to the target type. That is, in
int i;
std::cin >> i;
the >> operator looks for digit characters and figures out what value those characters represent. If the characters can't be converted to an integer value the extraction fails. Streams have a conversion to bool that tells you whether the stream is in a good state, or whether an attempted operation failed. So:
int i;
if (std::cin >> i)
std::cout << "got a value!\n";
To write a loop that prompts for valid input you need to reverse the test:
int i;
while (!(std::cin >> i) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To also check that the value is in the required range, just do it:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To clear the input stream, you have to reset its internal flags. You do that with std::cin.clear();. And, depending on what you think was typed in, you probably want to get rid of any additional characters that the user typed. You do that with std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n'). That tells the stream to discard character until it reaches a newline (press ENTER), or until it has read a huge number of characters.
Putting it all together:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
std::cin.clear();
std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Yes, this clears the stream state and flushes the input when the input was a valid integer but out of range; that's harmless. It's a waste of time, but the speed of keyboard input is limited by how fast the user types, which is much slower than anything that the code in this loop does.

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

Incorrect sum when adding up numbers

Ok, here's the code to add indefinite numbers and present the sum in c++. But error is that addition taking place is of first number and the last digits of all the other numbers. For example if i want to add 30 + 40 + 55 + 70, my program counts 30 + 0 + 0 + 5 + 0 = 35. What am I doing wrong?
#include <iostream>
using namespace std;
int main()
{
int num = 0;
int sum = 0;
cout << "Please enter numbers you want to add and end with N or n: ";
for (;;)
{
cin >> num;
sum += num;
cout << endl;
char indicator ('q');
cin >> indicator;
if (( indicator == 'n') || (indicator == 'N'))
break;
}
cout << "The sum is: " << sum << " ";
return 0;
}
I'm not sure I fully understand what you are trying to do, but if you want to add a list of integers terminated by an N (or n) character, then you should read each entity as a string, see if it's the terminating character, and if it's not, then convert it to an integer:
int sum = 0;
while (true) {
std::string s;
std::cin >> s;
if (tolower(s[0]) == 'n')
break;
sum += std::stoi(s);
}
Of course, the above code is only a skeleton -- in production code, you should always check if I/O operations succeeded and sanitize your input. A more complete example would be:
std::string s;
while (std::cin >> s) {
int ch = s[0];
if (ch > 0 && tolower(ch) == 'n')
break;
try {
sum += std::stoi(s);
} catch (const std::invalid_argument &e) {
// handle conversion error
break;
} catch (const std::out_of_range &e) {
// handle out-of-range error
break;
}
}
When you read the indicator, you extract the next non-blank character from the input stream; if the user has entered a number, this is the first digit. There are several ways of working around this.
The simplest is simply to loop on:
while ( std::cin >> num ) {
sum += num;
}
The input will fail if the next input doesn't have the form of a number (without extracting it). (This also has the advantage that you don't use the input if it fails for some reason.) This is more or less the standard idiom.
If you really do want to check for the 'n', you can use std::cin.peek() to look ahead one character, without extracting it. This doesn't skip white space, however, so you might want to do std::cin >> std::ws first. In this case, you'd probably want to wrap it in a function:
bool
terminationRequested( std::istream& source )
{
source >> std::ws;
return source.peek() == 'n' || source.peek() == 'N';
}
and then
while ( ! terminationRequested( std::cin ) ) {
int num;
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
You still have to check for a possible error after std::cin >> num. Otherwise, if the user enters "a", you'll end up in an endless loop, adding an undefined value to sum.
Alternatively, another frequent idiom is too use putback to return the indicator to the stream:
while ( std::cin >> indicator && indicator != 'n' && indicator != 'N' ) {
std::cin.putback( indicator );
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
Again, you'll have to handle the errors somehow. Using num if std::cin >> num fails is undefined behavior.
It's because you read the indicator character which will remove and ignore the next input digit by the user from the input stream.

while loop to infinity when the input of a cin is a 'dot'

I am having trouble using the cin method to acquire a variable. When the input is a number there is no problem, but when it is a special character like a dot [.],
the whileloop loops into infinity.
What am I doing wrong?
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}
I searched for the answer and i should have to flush the buffer but i don"t get how to do it. I'm rather new with c++. Thanx
Make race an char, then you will be able do to:
while (*race < '1' || *race > '3')
which is probably what you want to achieve.
Explanation:
When you cin >> into an int, it converts given ASCII string to integer value. . doesn't have an integer meaning, so it isn't read into race and failbit is set - further >>s are no-op, until you clear them. However, if you cin >> into char and compare it with other chars (well, their ASCII codes, actually), you will be able to check it without troubles.
This example exactly reproduces your problem:
#include <iostream>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
std::cin >> i;
}
}
Here's what happens: When operator>> fails to read an integer (e.g. when you type a dot and press enter), whatever you typed stays in the stream, including the newline character.
So in the next iteration of the while loop the next input is already there and since it's not a valid integer, the loop can never break.
You need to make sure that, when operator>> fails, you empty the stream and clear all the error flags that got set.
#include <iostream>
#include <limits>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
if (!(std::cin >> i))
{
// clear streams internal error flags
std::cin.clear();
// ignore what's left in the stream, up to first newline character
// or the entire content, whichever comes first
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
There are several problems with your code. The first is that you don't
verify that your input has succeeded; the correct condition for the
while should be:
while ( !cin || (*race < 1 || *race > 3) )
As written, if the input fails (which is what is happening when you
enter a '.', supposing that race has type int*), then *race
contains its previous value, whatever that was.
The second is that if you do get an error from cin, you don't clear
it. Once the stream is in an error state, it stays that way until you
explicitly clear it. If cin has failed, you need to execute:
cin.clear();
somewhere in the loop.
The third is that if cin fails, you don't extract the character which
made it failed, so that after clearing the error status, you need to
extract it. Given the way you've structured your dialog, you probably
want to ignore everything until the end of the line:
cin.ignore( INT_MAX, '\n' );
You may want to do this even if cin didn't fail, either in the loop
(if entered because of the *race < 1 || *race > 3 condition), or in
case of success. Alternatively, you may want to shift to reading lines,
and ensure that the line only contains whitespace after the character
you're interested in.
This last solution is the one I would adopt, since it handles pretty
much all of the above problems. So my code would look something like:
// return -1 on error in input,
// throw exception on (unexpected) end of file
int
getRace( std::istream& source )
{
std::string line;
if ( !std::getline( source, line ) ) {
throw std::ios_base::failure( "Unexpected end of file" );
}
std::istringstream tmp( line );
int results;
return tmp >> results >> std::ws && tmp.get() == EOF
? results
: -1;
}
// ...
int race = -1;
while ( race < 0 ) {
std::cout << "What is your race\n"
"1. Human\n"
"2. Troll\n"
"3. Zombie\n" << std::flush;
race = getRace( std::cout );
if ( race < 0 ) {
std::cout << "Wrong choice" << std::endl;
}
}
Note that by inputting through a line, you avoid any problems with
resetting format errors, skipping erroneous input or resynchronizing in
case of error.
The other solution besides the one accepted is to clear the cin's failbit and ignore the last input like below:
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
// Clears the state of cin to be in good state
cin.clear();
// Ignores the last input read so that it's not read back again
cin.ignore();
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}