How-To: Get valid integer input in C++ (a stupidly long solution to a stupidly simple problem)

Update: See the comments for a far, far more elegent and robust solution courtesy of the mighty shetboy!


One of the assessments I’ve got my diploma class doing at the moment is to fix all the bugs in some deliberately shonky C++ code. The code just asks for a name (string) and an age in years (int), and it then multiplies the age in years by 365 to give a rough indication of how many days you’ve been alive. So for example if I enter Al and 34 it comes back with:

Hi, Al! You’ve been alive for roughly 12410 days!

The problems come thick and fast though if you want to verify that the age in years entered is really an integer value. You CAN do so like this:

But you then end up with output like this where each character fails individually:

Obviously that’s no good, so I researched a bit and came up with a solution but –DAMN– it doesn’t feel like the right one… Check out all this clumsiness:

That works perfectly well as far as I’m concerned (remember – I’m not trying to validate the int to be within a given range or anything – I just want a valid int!) but something is surely wrong here… this should be a one-liner, or maybe three or four lines at the absolute most, not 140 lines or so…

Anyone got any suggestions on how to do this the right way? (In C++ not C, so no atoi or C-strings, and no boost library please! Just “standard” C++!).

7 thoughts on “How-To: Get valid integer input in C++ (a stupidly long solution to a stupidly simple problem)”

  1. Gosh, that is indeed clumsy. Can you use pre-made objects like in Java and then catch the exception? This will also work for -ve numbers, etc.

  2. Just spotted on this page

    Apologies if I messed up the markup code :)

    (r3dux: All good! It’s “cpp” for C++, list of valid languages for highlighting plus examples can be found here)

    1. That is absolutely perfect! You legend!!!

      With the code above tho the guy messed up and added two cin.ignore() statements so you need to push enter after each failed entry, I just did a quick mod to fix and added a top validation limit, which gives us this:

      That works beautifully, and saves 130 lines of clumsiness! I think you’ve unlocked an achievement!

      King of the Code achievement

      =D

      1. May as well refactor into a function:

        Still lovin’ it =D

        1. That’s good :)

          However it is preferable when developing functions like this to not output anything, they should be like submarines… silent running.

          The CALLING function should deal with IO, the LIBRARY function should deal with parsing the integer or whatever needs to be done. Exceptions should be used when things go wrong, then the calling function can do what is required.

          After all, the calling function may need to do different things depending on its context. The library function will have no idea what that could possibly be as it will be impossible to predict all scenarios.

          You will then be able to use the function for command line utilities, Windows Framework applications, QT, etc, etc.

  3. Great advice – which I’ve tried to take on board – but I feel like I’m losing the plot with all this =/

    48e-Get-Valid-Int-(Reusable-Function-Version).7z
    48f-Get-Valid-Int-(Unit-Test-Version).7z

    I know I should really have multiple projects in the same workspace to perform unit tests but I’m getting towards the end of it…

    If you have the time to take a quick swiz (they’re both Code::Blocks projects) and let me know if I’ve got the right end of the stick or if I’ve got the wrong stick entirely (which is the feeling I’ve got) then it would be greatly appreciated – no worries if not tho, I know you’re a busy bloke!

    /me hangs up his coding hat for the day…

Leave a Reply

Your email address will not be published.