Stuck in an infinite loop

In C ++, to handle incorrect inputs (for example, when a program asks for an integer, but you enter a character), it must be able to do something, and then loop to repeat the input.

My loop repeats endlessly when entering a character when an integer is required, and vice versa:

#include<iostream> int main() { while (cout << "Enter a number" && !(cin >> num)) { cin.sync(); cin.clear(); cout << "Invalid input; please re-enter.\n"; } } 

What should I do so that the program again asks for new input?

+4
source share
3 answers

If cin >> num fails, the invalid input must be removed from the stream. I suggest using ignore instead of sync to accomplish this. The reason in sync not guaranteed to remove the remaining input in all implementations of the standard library.

 #include <iostream> #include <limits> int main() { int num; while (cout << "Enter a number" && !(cin >> num)) { cin.clear(); // clear the error // Remove input up to a new line cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); cout << "Invalid input; please re-enter.\n"; } } 

The above example uses std::numeric_limits<std::streamsize>::max() used to extract the maximum number of characters that the input buffer can hold. This allows ignore() remove as many characters as possible before a new line. This is idiomatic C ++ and it is preferable to use magic numbers , which are likely to hide the problem that you currently have.

This works well, but does not handle situations where the input contains extra characters after the number. To deal with these situations, the cycle needs to be slightly modified to handle additional validation. One option is to read the whole line from cin , put it in std::stringstream , read the number from it, and then do an additional check. There is one special case that may need to be taken into account, although this is a line where the only characters after the number are spaces. Fortunately, the standard library provides a stream modifier std::skipws , which makes it easy to handle the situation. The example below shows how to do this without much effect.

 #include <iostream> #include <sstream> int main() { int num; for(;;) { std::cout << "Enter a number: " << std::flush; std::string line; std::getline(std::cin, line); // Read a line from console std::stringstream text(line); // store in a string stream char ch = 0; if(!(text >> num).fail() && (text >> std::skipws >> ch).fail()) { break; } std::cout << "Invalid input; please re-enter.\n"; } return 0; } 

The expression (text >> std::skipws >> ch).fail() skip all spaces that appear after the number, and then try to read one character. If the character is not available, reading will not be issued if the user enters only the number and nothing more. If we try to do this with cin , it will wait for the user to enter more text, even if the input is valid.

+5
source

Use cin.ignore() instead of cin.sync() and find out why from this answer

 while (cout << "Enter a number" && !(cin >> num)) { cin.clear(); // clear error cin.ignore(100, '\n'); // ignore characters until next '\n' (or at most 100 chars) cout << "Invalid input; please re-enter.\n"; } 

More on cin.ignore

Please note that you can expand the range of ignored characters to the maximum

  cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
+2
source

You can simply read the input as a string, convert it to an integer, and test it.

 #include <iostream> #include <string> using namespace std; int main() { int number = 0; string input; do { cout << "Enter a number: "; cin >> input; number = atoi(input.c_str()); // atoi returns 0 on error.. if (number != 0 || input.compare("0") == 0) // but maybe the user really entered "0". break; cout << endl; cout << "Invalid input; please re-enter.\n"; } while (1); cout << "You entered " << number << endl; return 0; } 

Program execution example:

 % ./foo Enter a number: abc Invalid input; please re-enter. Enter a number: 2 You entered 2 % ./foo Enter a number: 0 You entered 0 

.. although this is probably not the most elegant solution.

-1
source

Source: https://habr.com/ru/post/1483375/


All Articles