Thread: Validating an input

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    147

    Validating an input

    I want to accept an input which is a string, and from there, verify if the entry is an integer.

    To do this, probably I will have to divide the string and evaluate whether each character is within the ascii range for numbers, can anybody help me by giving me ideas on how i can achieve this, and is this possible? crashproof?
    Only by the cross are you saved...

  2. #2
    Registered User
    Join Date
    Jan 2003
    Posts
    115
    how about looking up the function atoi ?
    that might be helpful
    there are only 10 people in the world, those who know binary and those who dont

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >is this possible?
    Certainly.

    >crashproof?
    More difficult. This is a good start (not really elegant, but it works):
    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    
    static size_t numberOfDigits(int val)
    {
        size_t n = 0;
    
        while (val)
        {
            ++n;
            val /= 10;
        }
    
        return n;
    }
    
    static int validNumber(char *s)
    {
        size_t len = strlen(s);
    
        if (len > numberOfDigits(INT_MAX))
            return 0;
        
        while (*s)
        {
            if (!isdigit(*s++))
                return 0;
        }
    
        return 1;
    }
    
    int main(void)
    {
        char buff[BUFSIZ];
        int  num;
    
        printf("Enter a number: ");
        fflush(stdout);
    
        if (fgets(buff, sizeof (buff), stdin))
        {
            char *newline = strrchr(buff, '\n');
    
            if (newline)
                *newline = '\0';
    
            if (validNumber(buff))
            {
                num = (int)strtol(buff, 0, 0);
                printf("Your number (%d) was valid\n", num);
            }
        }
    
        return 0;
    }
    Another possibility is to ignore prevalidation and use the return codes from strtol to get your bulletproof conversion (code "borrowed" from Jack Klein ):
    Code:
    /* file usestrtol.c
    *
    *   15-Jul-2002
    *   (C) 1999 by Jack Klein
    *   All rights reserved
    *
    *   License granted for free non-commercial use
    *
    *   Description:
    *
    *   this program demonstrates the use of the standard
    *   library function strtol() prototpyed in <stdlib.h>
    *   to obtain and validate a signed integer value from the
    *   standard input stream
    *
    *   C++ notes:
    *
    *   On newer, ANSI/ISO Standard Conforming C++ compilers,
    *   the function strtol() is prototpyed in <cstdlib> and
    *   is in the std namespace
    *
    *   The strtol() function operates with an array of constant
    *   characters as its source which could be read with the
    *   cin.getline() member function instead of the C library
    *   fgets() function
    *
    *   It can even be called with the pointer returned by the
    *   c_str() member function for a std::string
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    
    int main(void)
    {
        char buff [25];
        char *end_ptr;
        long long_var;
        int int_var;
        for ( ; ; )
        {
            printf("Enter an int, return only to quit: ");
            fflush(stdout);
            fgets(buff, sizeof buff, stdin);
            
            if (buff [0] == '\n')
            {
                break;
            }
            
            errno = 0;
            
            long_var = strtol(buff, &end_ptr, 0);
            
            if (ERANGE == errno)
            {
                puts("number out of range\n");
            }
            else if (long_var > INT_MAX)
            {
                printf("%ld too large!\n", long_var);
            }
            else if (long_var < INT_MIN)
            {
                printf("%ld too small!\n", long_var);
            }
            else if (end_ptr == buff)
            {
                printf("not valid numeric input\n");
            }
    
            
            /* here is where you might want to add code to  */
            /* test for extra non-numeric characters at the */
            /* end of the input string, if you want that to */
            /* be an error                                  */
            /*                                              */
            /* if you want to generate this error, remove   */
            /* the two preprocessor lines that start with   */
            /* #if 0 and #endif                             */
            
            #if 0
            else if ('\0' != *end_ptr)
            {
                 printf("extra characters on input line\n");
            }
            #endif
            
            else
            {
                int_var = (int)long_var;
                printf("The number %d is OK!\n", int_var);
            }
        }
        return 0;
    }
    >how about looking up the function atoi ?
    atoi is far from crashproof. It results in undefined behavior if anything untoward happens, better to use strtol and cast to an int.
    My best code is written with the delete key.

  4. #4
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Here's another shot at it. I didn't see that it had to be an integer (so it checks for real numbers, though thats not hard to modify). It also checks for a prepending +/- on the number. Also, not exactly elegant, but a start.

    Code:
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
       char str[100];
       int is_number = 1;
       int decimal = 0;
       char* s;
    
       fgets(str, sizeof str, stdin);
    
       /* If the first character is not a digit, a +, or a
     -, then its not a number (continue no more). 
    Actually, for real numbers, the first character 
    could be a '.' as well, but I forgot about that. */
       if(!isdigit(str[0]) && str[0] != '-' && str[0] != '+')
       {
         is_number = 0;
       }
       else
       {
          /* Loop over the string until hitting a NULL terminator. */
         for(s = &str[1]; *s != '\0'; ++s)
         {
             /* If it isn't a digit, and it isn't a decimal 
    (note, if it is a decimal, but it is the second 
    one it fails as well), then its not a number, 
    and break the loop */
           if(!isdigit(*s) &&
    	  (*s == '.' && decimal != 0))
           {
    	 is_number = 0;
    	 break;
           }
    
             /* If it is a decimal, and it is the first one,
     then its okay, but register the decimal, and 
    continue. */
           if(*s == '.')
           {
    	 decimal = 1;
           }
         }
       }
    
       /* A result of 0 states that it was not a 
    number, a result of 1 states that it was. The 
    atoi is for comparison to that function 
    (seeing what it outputs if you did not enter a 
    number). */
       printf("Result: %d\n%d", is_number, atoi(str));
    
       return 0;
    }
    Last edited by Zach L.; 06-21-2003 at 12:11 PM.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  5. #5
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    i see, thank you all so much, but could you help me by inserting some comments, i understand the syntax of the code, but i am having trouble with identifying the purpose of certain segments of code, the purpose of some lines...
    Only by the cross are you saved...

  6. #6
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    How about a simple version, very similar to Zach's:

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #define MAXBUF 20    /* define maximum input size */
    int main()
    {
        char buf[MAXBUF];  /* input buffer */
        char *p;           /* temp buffer pointer */
        int    err = 0;    /* start with err = false */
    
        printf("Enter: ");
        fgets(buf, MAXBUF, stdin);  /* read a line */
        p = buf;                /* set the temp pointer */
        while (*p)              /* end when *p is '\0' */
        {
            if (!isdigit(*p))   /* is the character not a digit? */
            {                   /* no it's not -- set err to true */
                err = 1;
                 break;         /* exit the loop */
            }
             p++;            /* next character */
        }
    
    /* test err for 0/1 or false/true here */
    }
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  7. #7
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    i see, thanx! will try that out, looks easier to understand for me...

    also, how can i detect if the user has pressed the esc button?
    Only by the cross are you saved...

  8. #8
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    also, i tried using ur code WaltP, the 'isdigit' couldn't detect watever integer i entered as in put...is there anything wrong with it?
    Only by the cross are you saved...

  9. #9
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by fkheng
    also, i tried using ur code WaltP, the 'isdigit' couldn't detect watever integer i entered as in put...is there anything wrong with it?
    isdigit() only returns TRUE if the character passed is '0' - '9'. So my routine simply tells you whether the input is a number or not. any non-digit character will set err to 1 (true).

    If it is a number you will still have to convert the string into a number yourself.

    OOPS Warning...

    I forgot the following statement after the fputs():
    buf[strlen(buf)-1] = '\0';

    That will remove the \n from the buffer.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  10. #10
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    er...i don't see an fputs anywhere in the code, hehe...
    Only by the cross are you saved...

  11. #11
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    also, where should i convert the string to integer?
    coz the while loop needs the string in order to loop thru each character, so i can't convert it to integer at that point yet...

    any ideas?
    Only by the cross are you saved...

  12. #12
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by fkheng
    er...i don't see an fputs anywhere in the code, hehe...
    Sorry, I mistyped. fgets(), hoho

    also, where should i convert the string to integer?
    coz the while loop needs the string in order to loop thru each character, so i can't convert it to integer at that point yet...
    I'm not going to write the whole thing for you! Think about it.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  13. #13
    Registered User
    Join Date
    Jun 2003
    Posts
    147
    okay, but despite adding the clearing buffer line, my getchar() statement sitll seesm to leave an extra line and skip some other getchar statement of the loop...

    how can i get aroun dthis?
    Only by the cross are you saved...

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Originally posted by fkheng
    okay, but despite adding the clearing buffer line, my getchar() statement sitll seesm to leave an extra line and skip some other getchar statement of the loop...

    how can i get aroun dthis?
    Well you could actually post your code so we could tell you what's wrong. Because in this entire thread you have yet to post it a single time.

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Input class project (again)
    By Elysia in forum C++ Programming
    Replies: 41
    Last Post: 02-13-2009, 10:52 AM
  2. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  3. Structure and Linked List User Input Question
    By kevndale79 in forum C Programming
    Replies: 16
    Last Post: 10-05-2006, 11:09 AM
  4. Validating Monetary Input
    By Hexxx in forum C++ Programming
    Replies: 7
    Last Post: 02-01-2006, 08:27 AM
  5. need help with some input
    By blindleaf in forum C Programming
    Replies: 2
    Last Post: 03-16-2003, 01:50 PM