0

std::cin does not wait for user input after the first iteration if the user input was non-int. It works if the inputted value was an int outside of the range (0 to 65535).

while(true)
{
    std::cout << "Number to convert to 16-bit binary: ";
    float decimal;
    std::cin >> decimal;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    if(decimal > 0 && decimal < 65536)
        return decimal;
    else
        std::cout << "Invalid input. Try again.\n";
}

Expected result:

Number to convert to 16-bit binary: abc

Invalid input. Try again. (ask user for input again)

Actual result:

Number to convert to 16-bit binary: abc

Invalid input. Try again.

Number to convert to 16-bit binary: Invalid input. Try again.

...

Any help would be really appreciated.

Community
  • 1
  • 1
Luc1d
  • 1
  • 1
  • When you don't input a decimal number, cin fails. Maybe check the state of cin after reading? – cigien Apr 19 '20 at 20:00
  • `std::cin.clear()` seems to be on the menu (as does actually checking the results of your IO in the first place. i.e. `if (std::cin >> decimal)` etc. One of the many, many duplicates to this [can be found here](https://stackoverflow.com/questions/28031338/clear-entire-line-from-cin-instead-of-one-character-at-a-time-when-the-user-ente). – WhozCraig Apr 19 '20 at 20:00
  • @WhozCraig I read a little on std::cin.clear() and got the loop working. Thanks for your comment, helped me a lot. – Luc1d Apr 19 '20 at 20:12

1 Answers1

0

std::cin is simply an instantiation of the std::istream class.

Values can be extracted from an std::istream object (a template specialisation for std::basic_istream<char>) - as you have shown in your question - using its overload for the >> operator with floats (in your case).

The std::istream object will extract characters from the stream - possibly skipping starting whitespace characters, and until a trailing whitespace character is encountered - and attempt to convert them to a float value (storing the result in your decimal variable).

However, if the conversion could not be performed, zero is stored inside the variable, and the std::istream's std::ios_base::failbit is set.

Thanks to the conversion function to bool that has been defined for std::basic_ios (std::istream's parent class), an std::istream object - such as std::cin - can be used in conditional expressions, as so:

if (std::cin) {/* do this */}

Thus, you can simply check for a conversion error like so:

float f;
std::cin >> f;
if (!std::cin) {
    // ... deal with error here
}

However, the more idiomatic way to do the above is:

float f;
if (std::cin >> f) {
    // correct conversion, so can do stuff with f here
}
else {
    // conversion failed - deal with it here
}

The above works because all the >> overloads for std::istream return a reference to the std::istream object itself.

You can read up on all the >> overloads for std::istream here.