While loop doesn't end - c++

I rewrote this loop in several ways, with nested Ifs and do whiles, yet behavior is the same. It behaves as expected as long as the user does not enter a character or a string. Once the user does it just goes on spinning the loop until I CTRL+C it.
From what I have researched, when a variable is a number and the user inputs a char or a string, they just get converted into their ASCII numbers, in which case the while check should work. The number should be larger than allowed and the user should be prompted for a new value right? Why does it keep looping infinitely?
Width is declared as a float.
void setWidth ()
{
std::cout << "\nPlease enter the width (use numbers greater than 0 and no greater than 20.0).\n";
std::cin >> width;
while (width <= 0 || width > 20)
{
std::cin.clear();
std::cin.ignore();
std::cout << "You have entered a number outside of the allowed range.\nPlease enter a number greater than 0 and no greater than 20.\n";
std::cin >> width;
}
}
Like I said, for numbers it works great, doubles, negatives, whatever. But something like "asdf" or "a" will put it in infinitely spinning loop.
It seems like I've tried everything. Why does this happen? I mean I know why it loops, it's because the number is not between 0 and 20, but why does it not ask user for input? I do clear the buffer.

The line std::cin >> width; fails because the input isn't a number. It also doesn't consume any of the input, so you are stuck in an infinite loop.
To avoid this, you should read the input using std::getline(), then try to convert it (std::ostringstream is one option), handling and reporting failures accordingly.

The default for cin.ignore() is to ignore just a single character.
If you want to ignore longer strings, you have to add extra parameters for that, perhaps cin.ignore(1000, '\n') which skips up to 1000 characters or the next newline (whichever comes first).

cin::clear() "Sets a new value for the error control state" 1, but the remaining input is still here and still read.
Then I guess the actual behavior depends on the compiler since when I compile it with g++ 4.6.3 and type the input "abc", it only loops three times and then wait for another input.
To empty the cin buffer you may rather see How do I flush the cin buffer?

Try checking the failbit on cin

Ok, thanks for all the help guys... I finally managed to get it to work with cin (not getline), by doing exactly what ive been doing, except I made a clearBuffer() function. So instead of clearing the buffer from within the getWidth function, the getWidth function calls another function.. thereby leaves the getWidth function to execute some code... then comes back to run the rest of it...
For some reason when it goes outside of the function it works fine and strings and chars trigger the error.. but if the cin.clear and cin.ignore are kept within the function then I have that problem.
So the final code looks like this.
void clearBuffer()
{
std::cin.clear();
std::cin.ignore(80, '\n'); //Ignore the first 80 characters up to an Enter character.
}
void setWidth ()
{
std::cout << "\n\t\tPlease enter the width.\n(use numbers greater than 0 and no greater than 20.0).\n";
float temp = NULL; //Using temp here so that we dont write invalid characters to an actual variable.
std::cin >> temp;
clearBuffer();
while (temp <= 0 || temp > 20)
{
std::cout << "\nERROR: You have entered width outside of the allowed range.\nPlease enter a number greater than 0 and no greater than 20.\n";
std::cin >> temp;
clearBuffer();
}
if(temp > 0 && temp <= 20)
width=temp;
}

Related

Enter character instead int C++

I am writing a code that tally when an integer data type or character is entered.
int numero,
countInteger = 0;
countCharacter = 0;
while ( 1 ) {
try {
cin >> numero;
cout << numero;
throw numero;
} catch (...) {
countCharacter++;
cout << "Error";
}
}
If I entered Integer, counter in "countInteger" (but not show it in the code). If I enter a character, it is aa exception and recorded in "countCharacter".
But when I run the code generates an infinite loop and does not allow me to re-enter again. They could help me please. Guide me, you may have a bad concept.
When you try to read an integer, and you give something that's not an integer as input, there are two things happening: The first is that the stream gets its failbit set, the second things that happens is that the input is not extracted. So next iteration you read the same input again, and again and again...
I suggest another tactic: Read as a character, then see if it is a digit, an alphabetic character, or something else completely. Optionally, if you need the actual full number, read as a string, and try to convert to an integer.
A clarification: Input using std::cin is buffered. When you use the input operator >> then std::cin extracts characters from the buffer. If you try to read a number, but the first character in the buffer is not a digit, then the input operator will fail, and leave the character in the buffer.
Simple (hopefully) example:
Lets say you have this code
int number;
std::cin >> number;
std::cin >> number;
std::cin >> number;
As input for that part of the code, you enter
123abc
The first input will read 123 from the input, and stop at the letter, leaving the input as
abc
Now we come to the second input, and the code will see that the first character is not a digit, so it will set the failbit in the stream and leave the input as is:
abc
Then with the third input, the exact same thing as in the second happen.
Now imagine this was in a loop instead, the input operator >> will iteration after iteration see the non-digit input an promptly return, effectively giving you an infinite loop.
Now for a clarification of my suggestion... Depending on the goals and requirements of the program, you can instead read into a character and use the character classification functions to see what types you have.
Something like
int countDigit = 0;
int countCharacter = 0;
char ch;
while (std::cin >> ch)
{
if (std::isdigit(ch))
++countDigit;
else if (std::isalpha(ch))
++countCharacter;
else
{
// Not a digit or an alphabetic character
// I.e. newlines, spaces, control characters, etc.
}
}
Finally a note about using exceptions for this: Most people would consider it bad. Exceptions are for exceptions, exceptional cases, not as part of the normal flow of the program. Throwing an exception is expensive and disrupts the normal flow. Only use them for exceptional things, like errors.

How to stop an infinite loop due to invalid input C++

So I want to accept two inputs, a string and an int, and when the user enters "end" to exit out of the loop.
My problem is when "end" is entered that it gets stuck in a loop, since (I'm assuming) it is expecting two inputs when the user only types in one.
I've done some research and found stuff on discarding the input and resetting it with cin.ignore() and cin.clear(), however, these seem to only apply when accepting a single input, where as I'm asking for two separate inputs on one line, and it doesn't seem to work.
What my code is doing is basically asking for a list of things (name value), storing it in an array in a class, and is capped at 10 items. So, when "end" in entered, it only needs to exit the while loop. Everything else seems to work fine, i.e. when I enter 10 items it exits the loop and the rest of the code executes like it should. So there just seems to be a problem when typing in 'end'. (p.s. a is a string and b in an int type).
The section of code is:
do {
cout << "Enter the item and value (enter 'end' to stop): ";
cin >> a >> b;
items1.set_name(a, i);
items1.set_price(b, i);
i++;
} while ( i < 10 && a != "end" );
This seems like it should be very simple, and I'm sorry if its a stupid question, but I can't figure it out hahah.
Thanks in advance for helping me out.
You need to test the value of a BEFORE proceeding to read b; something like this:
cin >> a;
if(a == "end")
break;
cin >> b;
To get out of the loop, use
if (a == "end" || b == "end") break;

stop inupt if input no double

first of all I'm sorry for my
bad english.
I'm trying to read some numbers and write them into a vector in C++.
This should go as long as the input is a double number and the
loop should be stopped if the user writes an 'a'.
My Question is how can I check if the input is 'a'.
Breaking the loop is not the problem
while(true){
if(!(cin>>userInput)){
//here i want to know if the input is 'a' or some other stuff//
//also i want to do some other stuff like printing everything//
//what already is in the vector//
//when everything is done; break//
}
else
//the input is a valid number and i push it into my vector//
'userInput' is defined as double so the loop will stop.
My Problem is, if the user write 'q' the loop stops but it's instantly stoping the whole program. My try look like this:
while(true){ //read as long as you can
cout<<"Input a number. With 'q' you can stop: "<<endl;
if(!(cin>>userInput)){ //here the progam stops when the input is anything but a number
cout<<"How many numbers do you want to add up?"<<endl; //there are numbers in a vector that should be added up
cin>>numberOfAdditions;
break;
}
So I have a vector with some numbers the users writes down (20,50,90,...)
When the input is equal to 'q' (in this example everything but numbers )
the loop stops and I want to ask the user how many numbers should be added.
The cout-command is displayed but the input is beeing skipped.
So my program is not reading how many valued from the vector I want to add.
I hope you know what I mean and I don't want to use two questions and two variables to save the input but if it's not working without it I'll change my program.
Have a nice Day :)
Because your Input variable is of type double you have to flush the Input from cin before reading again. Otherwise there is still a newline in the buffer.
Consider the following example:
#include <iostream>
using namespace std;
int main(){
double userInput;
int numberOfAdditions;
while(true){ //read as long as you can
cout<<"Input a number. With 'q' you can stop: "<<endl;
if(!(cin>>userInput)){ //here the progam stops when the input is anything but a number
cout<<"How many numbers do you want to add up?"<<endl; //there are numbers in a vector that should be added up
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
cin.clear();
cin.ignore(INT_MAX,'\n');
cin >> numberOfAdditions;
break;
}
}
return 0;
}
The two Statements:
cin.clear();
cin.ignore(INT_MAX,'\n');
are flushing the Input stream until the newline is encountered.
The first answer already explains how to flush the cin stream after the user types in a char.
If you want to determine which character it was, you should define userInput as std::string. If the string is not "q" or "a" or whatever you are looking for, you have to cast the string to a double, just like this:
std::string str;
cin >> str;
if (str == "j")
// User typed in a special character
// ...some code...
else
double d = atof(str.c_str()); // Cast user input to double
Notice that the result of the cast is zero, if the user typed in any other string than the ones you especially look for.

Abusing cin in while loops for int assignment

simply trying to compare two user defined vectors to see if they are equal, current code:
vector<int> ivec1, ivec2; //vectors, uninitialized
int temp1;
cout << "Enter integers to be stored in ivec1." << endl;
while(cin >> temp1) //takes input from user and creates new element in the vector to store it
{
ivec1.push_back(temp1);
}
int temp2;
cout << "Enter integers to be stored in ivec2." << endl;
while(cin >> temp2) //same as above with different vector
{
ivec2.push_back(temp2);
}
if(ivec1 == ivec2)
cout << "ivec1 and ivec2 are equal!" << endl;
else
cout << "ivec1 and ivec2 are NOT equal!" << endl;
So far it lets me assign values to ivec1 just fine, but as I exit the while loop by entering a letter to make cin fail, it skips the second while block. Out of curiosity I tried putting in other cin statements after the first while loop, and it ignores them all as well.
Does forcing cin to fail cause the program to ignore all other calls for it or something, or is there another problem? If so, how can I get this program to do what I want?
screenshot for your viewing pleasure:
http://img695.imageshack.us/img695/2677/cinfailure.png
*PS. having temp1 and temp2 was just me trying to figure out if using the same int for both assignment loops was causing the problem, anyway I just figured I'd leave it there
You would have to do cin.clear() to reset the stream state. Then you will have to make sure that the offending character is read from the stream (using one of the techniques described here), so that the next input operation does not fail as well.
You mean that you a doing a ctrl-D to give end-of-file for the first loop.
The problem with that is that once EOF is achived it will persist and the second loop will also see the EOF and never read anything.
Instead use a terminating charater such as a blank line or a '.' and specifically test for that in toy while loop instead of while (cin >> tmp1)
Use cin.clear() between the loops. This command resets the state of the stream back to a usable one.
Might be helpful to know that you don't always have to enter an invalid character to exit a loop, you can also use (on windows) a ctrl-z (ctrl-d on other systems) on the console, which stimulates an EOF. You'd still have to cin.clear() (because an EOF still invalidates the stream) - but it's not as dangerous
When the first while loop exits because of failure of std::cin, it also sets the failure flag internally. All you need to clear that flag by writing the following after the first while loop:
scin.clear();
It clears all the failure flag, so that cin can be used to read further inputs.
I found this when I was working through the same problem. I had to add cin.clear() and cin.ignore() to reset the stream between loops and have it recognize the 'cin' calls again.

Trying to use a while statement to validate user input C++

I am new to C++ and am in a class. I am trying to finish the first project and so far I have everything working correctly, however, I need the user to input a number to select their level, and would like to validate that it is a number, and that the number isn't too large.
while(levelChoose > 10 || isalpha(levelChoose))
{
cout << "That is not a valid level" << endl;
cout << "Choose another level:";
cin >> levelChoose;
}
That is the loop I made, and it sometimes works. If I type in 11 it prints the error, and lets me choose another level. However if the number is large, or is any alpha character it floods the screen with the couts, and the loop won't end, and I have to force exit. Why does it sometimes stop at the cin and wait for user input, and sometimes not? Thanks for the help!
This is an annoying problem with cin (and istreams in general). cin is type safe so if you give it the wrong type it will fail. As you said a really large number or non-number input it gets stuck in an infinite loop. This is because those are incompatible with whatever type levelChoose may be. cin fails but the buffer is still filled with what you typed so cin keeps trying to read it. You end up in an infinite loop.
To fix this, you need to clear the fail bit and ignore all the characters in the buffer. The code below should do this (although I haven't tested it):
while(levelChoose > 10 || isalpha(levelChoose))
{
cout << "That is not a valid level" << endl;
cout << "Choose another level:";
if(!(cin >> levelChoose))
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
Edit: numeric_limits<> is located in the limits include:
#include<limits>
From your description, it seems likely (nearly certain) that levelChose is some sort of numeric type, probably an integer.
When you use operator>> to read a number, anything that couldn't be part of a number (e.g., most letters) will be left in the input buffer. What's happening is that you're trying to read the number, it's failing and leaving the non-digit in the buffer, printing out an error message, then trying to read exactly the same non-digit from the buffer again.
Generally, when an input like this fails, you want to do something like ignoring everything in the input buffer up to the next new-line.
levelChoose appears to be an integer type of some form (int, long, whatever).
It's not valid to input a character into an integer directly like that. The input fails, but leaves the character in the incoming buffer, so it's still there when the loop comes around again.
Here's a related question: Good input validation loop using cin - C++
I suspect the part while(levelChoose > 10..... This does not restrict level to less than 10 (assuming greater than 10 is a large number in your context). Instead it probably should be while(levelChoose < 10...
To check that an expression is not too large, the following could be a possibility to validate (brain compiled code!!)
const unsigned int MAX = 1000;
unsigned int x;
cin >> x;
while(x < MAX){}