Thread: integer validation skips errors?

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    15

    integer validation skips errors?

    well heres the code:

    Code:
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    
    
    bool ReadInt(int *value);
    
    
    
    int main ()
    {
    	int userInteger;
    	
    
    
    	cout << "Please enter an integer value : ";
    
    	while (!ReadInt(&userInteger))
    	{
    		cout << "Invalid input!\n";
    		cout << "Please enter an integer value : ";
    	}
    
    
    	
    
    	cout << "The valid values are:\n";
    	cout << "\tInteger : " << userInteger << endl;
    	
    
    	return 0;
    }
    
    
    
    bool ReadInt(int *value)
    {
        bool noErrors = true;
        
        char array[10];
         
        int i = 0;
    
        cin.getline (array, 10);
        
    
        if ((array[0] != '-') || (array[0] < '0' && array[0] > '9'))
        {
           noErrors = false;
        }
        else
        {   while ( i < strlen(array))
            {
                if ( (array[i] < '0') || (array[i] > '9'))
                noErrors = false;
            i++;
            }
        }
        if (noErrors = true)
        {
           *value = atoi(array);
            
        } 
    return noErrors;
    }

    but when it runs, it skips over the errors...
    example:

    enter 5, and its right
    enter a5, and it says the valid integer is 0
    enter 11 numbers, and it cuts the first off
    enter 5a, and it says the valid integers are 5

    ive gone through it line-by-line, but i cant find the error...

    can you C++ gurus out there help me? i appreciate it...

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Code:
    (array[0] < '0' && array[0] > '9')
    How can the value be less than '0' AND be greater than '9'? I think you wanted an OR there instead of an AND.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Oh, and there is an easier way of doing what you are trying to accomplish using strtol(). It might be worth looking into.

  4. #4
    Registered User
    Join Date
    Jun 2004
    Posts
    11
    Code:
     if (noErrors == true)
    	{
    	   *value = atoi(array);
    		
    	} 
    return noErrors

  5. #5
    Registered User
    Join Date
    Sep 2004
    Posts
    15
    *slaps forehead*

    ok, now....if you put in more than 9 characters, it loops infinitely with "invalid input", is there a way to write an if statement to stop this?

  6. #6
    Registered User
    Join Date
    Sep 2004
    Posts
    15
    grr!...now it doesnt work...
    as soon as i changed
    Code:
     if (noErrors = true)
    to
    Code:
     if (noErrors == true)
    it spits out 'invalid input'....i dont get it...i corrected the '=', tested it and everything worked fine so i saved it. then i turn my comp on today to run it again, and now somethings wrong.
    Last edited by 2fastwrx; 10-24-2004 at 08:47 PM.

  7. #7
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    The stream is failing because member getline runs out of space if you type more than 9 digits. Keep in mind that one character is used for the terminating zero. The way that getline, and all the other stream operations tell you about such problems is by setting state flags, in this case failbit. After you perform an operation if cin.good() is true then everything worked, if cin.fail() is true then it could not perform the operation, but no data was lost and it's waiting for you to fix the problem. The way you tell the stream that you are ready to try again is by calling cin.clear(). Until you do this all operations will no-op.


    Thus we can re-write ReadInt like so.

    Code:
    bool ReadInt(int &n) {
        std::cin >> n;
        if(std::cin.good()) return true;
        std::cin.clear();
        std::cin.ignore(MAX_INT);
        return false;
    }
    This skips any leading whitespace (including newlines) and starts reading digits into the int, if the first character it finds is a non-digit then it leaves the character where it found it and sets failbit. We then clear the state and simply ignore the rest of the line. The confusing part may be that 5q will be parsed as 5 and the stream will be good. The next attempt to read an int will hit the 'q' and then fail.

    If you want to force one int per line.
    Code:
    bool ReadInt(int &n, std::istream &is=std::cin) {
        if(is >> n && is.peek() == '\n') return true;
        is.clear();
        std::string line;
        if(std::getline(is,line)) {
            std::cerr << "Expected int, read \"" << line << "\"\n";
        } else std::cerr << "Stream hopelessly courupt" << std::endl;
        return false;
    }
    In this I pass in a reference to an istream, and default it to standard input, I like to do this with any function that might need to work with files or whatever. This also lets me type just "is" rather than "std::cin", without the nastyness of using namespace std. The confusing if statement takes advantage of the fact that if you try to evaluate a stream as a bool it will return true if the stream is good, and the fact that most stream operations return the stream. peek() returns the next character without removing it. I also used the new version of getline thats slightly different in that it is a function, rather than a member of istream, and it doesn't suck.

  8. #8
    Registered User
    Join Date
    Sep 2004
    Posts
    15
    wow. the code you use is a bit above me right now, but i appreciate the effort
    eventually i found out that my logic operators were wrong, and all of my or's shoulda been and's...now i gotta figure out how to prevent more than 10 characters from being entered...

  9. #9
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    you can't prevent them from entering more than 9 char. You can limit the number of char that goes into your variable array, however, using the getline limit parameter, as you did, or by accepting up to 256 or some ridiculously high number of char in array using getline().

    char array[256];
    cin.getline(array, 255);

    then use strlen() to determine how many char were entered. If the answer is more than 9, display an error message or whatever.

    int length = strlen(array);
    if(length > 9)
    cout << "invalid input";

  10. #10
    Registered User
    Join Date
    Sep 2004
    Posts
    15
    that worked great. now to validate a float: i was thinking of a counter for the decimal points, in order to make sure more than one is not entered (not neccessary, but extra). i was gonna use a for loop...

    Code:
    for (periods = 0; periods < strlen (array); periods++)
    {
        if(periods>1)
        {
            noErrors = false;
            //if more than 1 decimal is found, its an invalid entry
        }
    }
    i just tested it before i posted this, and it works...so im done with everything, thanks all!!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Program giving errors
    By andy bee in forum C Programming
    Replies: 5
    Last Post: 08-11-2010, 10:38 PM
  2. Replies: 7
    Last Post: 08-19-2007, 08:10 AM
  3. Errors with program to replace string with another
    By Dan17 in forum C Programming
    Replies: 3
    Last Post: 09-14-2006, 10:15 AM
  4. Operator Overloading (Bug, or error in code?)
    By QuietWhistler in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2006, 08:38 AM
  5. errors in class(urgent)
    By ayesha in forum C++ Programming
    Replies: 2
    Last Post: 11-10-2001, 06:51 PM