Thread: Advice on basic number validation

  1. #16
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Can someone explain with more details, please?
    Actually, I dont know, or fully understand, the details either.
    I've been digging up the C++ standard, and so far have found:

    From basic_istream (27.6.1.3):
    int sync();
    Effects: Behaves as an unformatted input function (as described in 27.6.1.3, paragraph 1), except that it
    does not count the number of characters extracted and does not affect the value returned by subsequent
    calls to gcount(). After constructing a sentry object, if rdbuf() is a null pointer, returns -1 . Otherwise,
    calls rdbuf()->pubsync() and, if that function returns -1 calls setstate(badbit)
    (which may throw ios_base::failure (27.4.4.3), and returns -1. Otherwise, returns zero.

    From basic_streambuf (27.5.2.2.2):
    int pubsync();
    Returns: sync().

    From basic_streambuf (27.5.2.4.2):
    int sync();
    Effects: Synchronizes the controlled sequences with the arrays. That is, if pbase() is non-null the characters
    between pbase() and pptr() are written to the controlled sequence. The pointers may then
    be reset as appropriate.
    Returns: -1 on failure. What constitutes failure is determined by each derived class (27.8.1.4).
    Default behavior: Returns zero.

    From basic_streambuf (27.5.2.3.2):
    char_type* pbase() const;
    Returns: The beginning pointer for the output sequence.
    char_type* pptr() const;
    Returns: The next pointer for the output sequence.


    Somehow cin.sync() effectively seems to flush the input buffer, from what I see.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  2. #17
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Quote Originally Posted by Lithorien
    OP: You approach isn't going to get you where you need to go. Take a look at this and see if it helps.



    This will work if the user enters a char and not a number, as well as if the user enters a number.

    Code:
    #include <iostream>
    
    int main()
    {
    	bool valid = 0;
    	
    	do
    	{
    		char *ans = new char;
    		int num = -1;
    		
    		std::cout << "Input a number (0-9): ";
    		std::cin >> ans;
    		
    		if (isdigit(*ans))
    		{
    			num = atoi(ans);
    		}
    		
    		if ((num < 0) || (num > 9))
    		{
    			std::cout << "\nInvalid number.\n\n";
    		}
    		
    		else
    		{
    			std::cout << "\nYour number was: " << num << ".";
    			valid = 1;
    		}
    	}
    	while (valid == 0);
    	
    	std::cin.ignore(80, '\n');
    	std::cin.get();
    	return(0);
    }
    I just feel I need to point this out.

    Your approach opens for alot of errors.
    First:
    you use new but never call delete, that means you have created a memoryleak. Also, that new is totally uncalled for.

    Second:
    std::cin >> ans;
    should be std::cin >> *ans; since we are dealing with pointers.

    Third:
    atoi expects an array of chars, you send it a pointer to one char. This I suspect can result in undefined behavour (sp?). Either way you should send a null-terminated string to atoi.

    Sorry if it seems like im whining, I just think these things are important enough to point out.

  3. #18
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    Quote Originally Posted by Shakti
    I just feel I need to point this out.

    Your approach opens for alot of errors.
    First:
    you use new but never call delete, that means you have created a memoryleak. Also, that new is totally uncalled for.
    The new has a place. Try it with just a normal char and you introduce a lot of pain -- however you're right, I did forget delete. Thank you.

    Quote Originally Posted by Shakti
    Second:
    std::cin >> ans;
    should be std::cin >> *ans; since we are dealing with pointers.
    No it doesn't. You're dealing with a pointer, yes, but if you just go >> ans, you'll be storing in the memory pointed to by ans anyway.

    Quote Originally Posted by Shakti
    Third:
    atoi expects an array of chars, you send it a pointer to one char. This I suspect can result in undefined behavour (sp?). Either way you should send a null-terminated string to atoi.

    Sorry if it seems like im whining, I just think these things are important enough to point out.
    atoi() is recieving the value pointed to by ans, not a pointer to ans. Take a look at isdigit() -- THAT is recieving a pointer.

    Yet again, however, good point about the non-null termination. Thank you for that - just change 'new char' to 'new char[255]', and any reference to 'ans' with 'ans[0]'.

  4. #19
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Ummm, you have it all wrong, take this
    Code:
    int *p = new int;
    *p = 5;     // Now I change the value.
    cout << *p << endl;     // This will in my example print 5
    cout << p << endl;       // This will print the address p points to.
    Now that was about the pointer.
    So from that we can make out that in your code isdigit gets the value (isdigit(*ans)) and atoi gets the address which the pointer points to (atoi(ans))

    Lets go on to the new thingy:
    You can safely do this:
    Code:
    for(;;)
    {
        int i = 0;
        // bla bla bla
    }
    Because i will go out of scope when the loop does another pass.

    Last but not least, the cin-problem.
    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int *p = new int;
    	cin >> p;
    }
    This gives me 22 errors with MingW which is one of the most standard-complaiant (sp?) compilers out there.

    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int *p = new int;
    	cin >> *p;
    }
    This gives me 0 errors on the same compiler.
    Last edited by Shakti; 04-02-2005 at 01:42 PM.

  5. #20
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Hmm, this discussion is becomming more and more interesting...
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  6. #21
    Registered User
    Join Date
    Sep 2005
    Location
    NJ
    Posts
    2

    Input Validation - User enters float

    Quote Originally Posted by Micko
    My solution is...
    Code:
    #include <iostream>
    
    int main() 
    {
        using namespace std;
        
        int num;
        cout<<"Enter integer: ";
        cout.flush();
        while (!(cin>>num))
        {
             
                  cout<<"Wrong input!"<<endl;
                  cin.clear();
                  cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
                  cout<<"Enter again: ";
                  cout.flush();
        }
        if(cin.get() !='\n')
        {
    			//something is left in an input buffer, dicard it...
    		cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
        }
    
        cout<<"You entered"<<num; 
    }
    I think this would be a better solution, if someone has better please post so we can all benefit...
    Hello,

    I subscribed to get help with a similar problem from my C++ course and saw this thread. I wanted to add some things I found when working with cin. I think the above handles validation of entering a single int. Now suppose you have a case where you have to enter another int immediately after this. For example:

    int num;
    cout<<"Enter integer: ";
    cout.flush();
    while (!(cin>>num))
    {

    cout<<"Wrong input!"<<endl;
    cin.clear();
    cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
    cout<<"Enter again: ";
    cout.flush();
    }
    if(cin.get() !='\n')
    {
    //something is left in an input buffer, dicard it...
    cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
    }

    cout<<"You entered"<<num;

    int num2;
    cout<<"Enter another integer: ";
    cout.flush();
    while (!(cin>>num))
    {

    cout<<"Wrong input!"<<endl;
    cin.clear();
    cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
    cout<<"Enter again: ";
    cout.flush();
    }
    if(cin.get() !='\n')
    {
    //something is left in an input buffer, dicard it...
    cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
    }

    cout<<"You entered"<<num;

    If you use the above code, it handles entry and validation of the first number. It handles the case where the user enters a letter instead of a int; however, what happens when the user enters something like 10.6 for the first number? Well, I can tell you that it stores the integer part 10 in num and then when calling

    cin >> num2;

    cin goes into the error state because it tries and fails to put the .5 into num2, e.g. it is looking for an int and finds a float on the input stream. I think the only way to do the validation is using the old method of reading the entire line and parsing the line with the sscanf(), as one person already posted above. If anyone can show an elegant way to do validation checking and handle the more complex case of the user entering a float when expecting an int, please post. I am most interested in this. We are covering some of this in my C++ class but I have not found a way to handle the case where the user enters a float when the program is expecting a second int right after the first.

    From everything I've seen, I think you have to use the old technique that was posted as a link earlier in the thread:

    http://faq.cprogramming.com/cgi-bin/...&id=1043284392

    Thanks,

    Steve

  7. #22
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Did you run that code? It does not do what you say it does. In fact, it handles an input of 10.6 correctly.

    That is because of the if statements after the while statement. If the next character after the input is not a newline, it ignores everything up to the newline. So since '.' is not a newline, it ignores the '.', '6', and '\n' and is ready for the next input.

    If you are having trouble with handling a float when expecting an integer, start a new thread with the full code in code tags and the input you are giving it.

  8. #23
    Registered User
    Join Date
    Sep 2005
    Location
    NJ
    Posts
    2
    Thanks for the suggestion Daved. You are correct. The code does ignore the .x portion of the floating point value that is entered and goes on without putting cin into the error state. But, in the real world (IMHO), if a user enters a float where an int is expected, I think they should be warned and prompted to enter an int. They might have been entering data from the wrong column on their paper or some other user error.

    The good thing is that I can see how to extend your code to do that perfectly. That is all I am going to worry about since I am learning C++ and not input validation techniques right now.

    I am new here, so I will have to find out how to start a new thread and, as you suggest, post the code. I'll also have to read the help pages about posting code, so I understand how to separate that from the rest of my text. Thank you for correcting my mistake!

    Regards,

    Steve

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memory issue
    By t014y in forum C Programming
    Replies: 2
    Last Post: 02-21-2009, 12:37 AM
  2. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  3. Learning Memory, Ins and Outs?
    By Zoiked in forum C Programming
    Replies: 1
    Last Post: 08-27-2007, 04:43 PM
  4. Issue w/ Guess My Number Program
    By mkylman in forum C++ Programming
    Replies: 5
    Last Post: 08-23-2007, 01:31 AM
  5. help with a source code..
    By venom424 in forum C++ Programming
    Replies: 8
    Last Post: 05-21-2004, 12:42 PM