简体   繁体   中英

While loop doesn't end

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?

尝试检查cin上的failbit

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM