Newbie: Validation of Integer when <ENTER> key has been pressed.

This is a discussion on Newbie: Validation of Integer when <ENTER> key has been pressed. within the C++ Programming forums, part of the General Programming Boards category; Greetings, I want to prompt the user to enter todays date in format of dd/mm/yyyy First they enter the day ...

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    5

    Unhappy Newbie: Validation of Integer when <ENTER> key has been pressed.

    Greetings,

    I want to prompt the user to enter todays date in format of dd/mm/yyyy

    First they enter the day (dd) i.e. 1 - 31 into integer variable dd

    The validation routine is as follows:-
    • Is the day value EMPTY i.e. they hit the ENTER KEY then re-prompt for day value.
    • Is the day value an integer, if not then re-prompt for day value.
    • If the day value is an integer ensure its between 1 - 31 if not not then re-prompt for value else continue.


    Im at my wits end for such a simple problem, as I cannot for the life of me trap when the user hits return.

    Knowing
    Code:
    cin.fail
    won't trap this I then use
    Code:
    cin.get()
    but having to check intially when they enter the value and then again for when they are prompting due to a fail on one of the other validation checks has become too complicated for me.

    I have the following code below:-
    Code:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int dd;
        bool validDay = false;
    
        //Prompt and valdiate day entry
        //Loop until date is valid
        cout << "\n\tPlease enter todays date:-\n\n";
        cout << "\tPlease enter day e.g. 1 - 31 :";
        cin >> dd;
    
    
        while(!validDay)
        {
                //Check if enter has been pressed
    
                //Do IF day IS entered IS a number
                if (!cin.fail())
                {
                    //Is day value valid
                    if (dd >=1 && dd <=31)
                    {
                        validDay = true;
                    }
    
                    else
                    {
                        cout << "\n\tInvalid day, please enter day value between 1 - 31 :";
                    }
                }
    
                else // The user enter something other than a number, doh!
                {
    
                    while (cin.fail())
                    {
                        cin.clear();
                        cout << "\n\tWarn: Please enter a NUMBER ONLY between 1 - 31 :";
                        cin.ignore(80, '\n');
                        cin >> dd;
                    }
                }
        }
    }
    Can anyone please assist? I think Im making it too complicated.

    I believe I will have to check if they haven't entered a value on initial prompt and re-prompts if they entered a non-numeric value or if they entered a number <= 0 or > 31

    Thanks
    Rob

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,414
    At the glance, it looks like the main problem is that despite prompting the user to re-enter when the day value is out of range, you never actually try and read it in again. This could be solved by moving the cin >> dd; into the start of the loop.

    With that in place, you can then simplify the non-integer input handling part.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    5
    Quote Originally Posted by laserlight View Post
    At the glance, it looks like the main problem is that despite prompting the user to re-enter when the day value is out of range, you never actually try and read it in again. This could be solved by moving the cin >> dd; into the start of the loop.

    With that in place, you can then simplify the non-integer input handling part.
    That was me being careless but I don't understand how logically I can check for all things.
    Im going for a break from the pc and look at it later with a clear head :-)

    I had while loops e.g.
    Code:
    while (cin.get() != '/n')
    and got myself in logic nightmares... ahh time to move away from the pc.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,414
    Quote Originally Posted by robtyketto
    That was me being careless but I don't understand how logically I can check for all things.
    Im going for a break from the pc and look at it later with a clear head :-)
    Good idea

    By the way, when I talk about simplifying the non-integer input handling part, I mean that the inner while loop is unnecessary, and of course if you move the first cin >> dd; into the loop, you don't need another one.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    5
    Modified code, but the cin.get() detects when I press enter even if I entered a number beforehand.


    Code:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int dd;
        bool validDay = false;
    
        //Prompt and valdiate day entry
        //Loop until date is valid
    
        cout << "\n\tPlease enter todays date:-\n\n";
        cout << "\tPlease enter day e.g. 1 - 31 :";
        cin >> dd;
    
    
        while(!validDay)
        {
                //Check if enter has been pressed
    
                //Do if value is NUMERIC or ENTER KEY
                if (!cin.fail())
                {
                    //Has anyone pressed ENTER?
                    if (cin.get() == '\n')
                    {
                         cout << "Enter Key pressed";
                    }
    
                    //Numeric value entered just not between 1 & 31
                    else if (!(dd >=1 && dd <=31))
                    {
                        cin.clear();
                        cin.ignore(80, '\n');
                        cout << "\n\tWarn: Please enter a valid day between 1 - 31 :";
                        cin >> dd;
                    }
    
                    else  // Number is between 1 and 31
                    {
                        validDay = true;
                    }
                }
    
                else // The user enter something other than a number, doh!
                {
                        cin.clear();
                        cin.ignore(80, '\n');
                        cout << "\n\tWarn: Please enter a NUMBER ONLY between 1 - 31 :";
                        cin >> dd;
                }
        }
    }
    Last edited by robtyketto; 05-08-2009 at 12:48 PM.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    You don't need to check for <enter> to see if they typed enter without inputting a number. I'd remove the cin.get() check completely.

    The reason is that operator>> skips initial whitespace. So if the user hits enter without typing anything, cin will continue to wait for them to type something and control won't return to your program until they actually do type something and hit enter.

    This means they can hit enter 100 times, then type in 10 and hit enter again and it will work. Usually that's fine, but if that is not what you want you'd have to add more complicated input code that uses getline and a stringstream.

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    5
    Quote Originally Posted by Daved View Post
    You don't need to check for <enter> to see if they typed enter without inputting a number. I'd remove the cin.get() check completely.

    The reason is that operator>> skips initial whitespace. So if the user hits enter without typing anything, cin will continue to wait for them to type something and control won't return to your program until they actually do type something and hit enter.

    This means they can hit enter 100 times, then type in 10 and hit enter again and it will work. Usually that's fine, but if that is not what you want you'd have to add more complicated input code that uses getline and a stringstream.
    I suspected as much, I think for simplicity I will get rid of the cin.get() and just let them press enter as many times as they wish.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,414
    Oh, now I understand your first requirement.

    It is going to be tough to explain to you exactly what to do, but seeing how hard you have tried, I am going to give you a working example:
    Code:
    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    int main()
    {
        //Prompt and valdiate day entry
        int dd;
        cout << "\n\tPlease enter todays date:-\n\n";
        cout << "\tPlease enter day e.g. 1 - 31 :";
    
        bool dayIsValid = false;
        string line;
        while (!dayIsValid && getline(cin, line))
        {
            if (line.empty())
            {
                cout << "\n\tPlease enter todays date:-\n\n";
                cout << "\tPlease enter day e.g. 1 - 31 :";
            }
            else
            {
                stringstream ss(line);
                if (ss >> dd && ss.eof())
                {
                    if (dd >= 1 && dd <= 31)
                    {
                        dayIsValid = true;
                    }
                    else
                    {
                        cout << "\n\tWarn: Please enter a valid day between 1 - 31 :";
                    }
                }
                else
                {
                    cout << "\n\tWarn: Please enter a NUMBER ONLY between 1 - 31 :";
                }
            }
        }
    
        if (dayIsValid)
        {
            cout << dd << endl;
        }
        else
        {
            cout << "\n\tInput error" << endl;
        }
    }
    So, the most obvious change is that instead of reading directly into dd, I read a line into a string object. This allows you to handle the case where the user enters a blank line.

    Now, if the user did enter something, we need to get it into dd. This is done with the help of a stringstream. If ss >> dd evaluates to true, it means that there was no input failure. But it could still be the case that the user entered say, "12a", in which case we would like to treat it as an error. This is done by checking ss.eof(). If ss.eof() is also set, we can assume that the input consists only of the integer, thus we just need to validate the range.

    I retain the use of a validity flag because it is possible for the user to simulate EOF instead of entering input. This would cause the loop to be terminated with dd not being set.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    May 2009
    Posts
    5

    Smile

    Thanks for the replies.

    I plan to try out the example and then look up a few things and mess around abit to ensure I understand it fully.

    Much appreciated :-)

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    242
    Disclaimer: I'm a total newbie at this, so please forgive me for any stupidity. On the other hand: Gotta learn it sometime...

    Anyhow, if the user presses enter, then cin.fail() should be 0, right? It seems to me that it didn't fail, but we still have an empty value for dd.

    Assuming that's the case, then the first if condition holds.

    But I don't understand why you even need the special case for enter, since it seems to me that your first "else if" captures the case of pressing enter key (just doesn't give a special message).

    In any case, if the enter key is pressed, doesn't the condition (!(dd >=1 && dd <=31)) hold?

    And if you want a special message for enter key, won't the code from the else if statement work?

    Anyhow, it seems to me (as newbie without running it) that in your original code, the user has no opportunity to re-enter a value for dd after hitting enter--in which case first if and then the nested if both hold, but the loop will never get to a cin statement.

    Some of the other options offered are over my head, so I'll leave it at that.

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    >> if the user presses enter, then cin.fail() should be 0, right?

    In the case of operator>>, if the user presses enter only, nothing will happen. The program will continue to wait for more user input, and when input is given the initial newline will be ignored as if it never existed. So most of the rest of your thoughts are moot.

    If you're using cin >> to read in data, then you can ignore the case of the user typing in extra whitespace (like hitting enter, tab or space) before they type their answer. It is only if you don't want to ignore that and handle it specifically do you need to do some extra work like laserlight did with getline and a stringstream.

  12. #12
    Registered User
    Join Date
    May 2009
    Posts
    242
    Dave: Thanks again for your clear and helpful answer as well as your patience!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. validation problem in a loop (newbie question)
    By Aisthesis in forum C++ Programming
    Replies: 11
    Last Post: 05-10-2009, 10:47 PM
  2. Looking for constructive criticism
    By wd_kendrick in forum C Programming
    Replies: 16
    Last Post: 05-28-2008, 09:42 AM
  3. Linked Lists Integer addition ? HELP Please??
    By green_eel in forum C Programming
    Replies: 3
    Last Post: 03-12-2003, 03:36 PM
  4. RETURN key pressed!!!!!!
    By RISF in forum C++ Programming
    Replies: 2
    Last Post: 12-06-2001, 04:07 AM
  5. BST/Red and Black Tree
    By ghettoman in forum C++ Programming
    Replies: 0
    Last Post: 10-24-2001, 10:45 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21