Program to take a number from 0 to 9 as input I'm trying to make a function that requests a number from 0 to 9 to the user and that is robust. I've been looking at code to guide me and most fail to find any of these situations, usually due to the use of cin:

If the user enters spaces before or after the number, the entry is valid
If you end the input (Ctrl+Z in Windows; Ctrl+D on most Unix) an infinite cycle is produced
If the user typed 2ff the entry is valid
The entry is waiting for us to type something because of a line jump

I've made the following code and I don't think it fails with its purpose. I would like to know your opinion and if you believe in any case where it could fail or if I can improve it.
#include &lt;iostream&gt;
#include &lt;string&gt;

using namespace std;

int input_number()
{

    string data = &quot;&quot;;
    while (true)
    {

        cout &lt;&lt; &quot;Input: &quot;;
        if (!getline(cin, data))
        {
            return -1;
        }
        if (data.length() != 1 || isspace(data[0]))
        {
            cerr &lt;&lt; &quot;Invalid number, try again!&quot; &lt;&lt; endl;
            continue;
        }
        try
        {
            return stoi(data);
        }
        catch (const exception &amp;e)
        {
            cerr &lt;&lt; &quot;Invalid number, try again!&quot; &lt;&lt; endl;
            cin.clear();
        }
    }
}

int main()
{

    cout &lt;&lt; input_number() &lt;&lt; endl;
}
This can be rewritten using regular expression \s*(\d)\D* (zero or more whitespace characters, a single digit, zero or more non digit characters. If I understand correctly, heading and trailing spaces are ok, 2ff is ok but ff2 is not ok and 23 is not ok either.
int input_number() {
  static const std::regex valid_number(&quot;\\s*(\\d)\\D*&quot;);
  string data;
  std::smatch matches;
  while (true) {
    cout &lt;&lt; &quot;Input: &quot;;
    if (getline(cin, data) &amp;&amp; 
          std::regex_match(data, matches, valid_number)) {
        return stoi(matches[1]);
    }
    cerr &lt;&lt; &quot;Invalid number, try again!&quot; &lt;&lt; endl;
  }
}

The exception on parsing should never be thrown, regular expression takes care to feed only valid number as the input. The initial version contained try/catch construct to catch it anyway and assert false but this idea is probably over-engineering.