Thread: How to force user to input a value in the type limit

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    84

    How to force user to input a value in the type limit

    Hi guys,

    I read this brilliant post by hammer about, how to get numbers safly using strtol() function.

    My question is, how can I make sure the user DO NOT exceed the type limit??
    Code:
    if (fgets(buf, sizeof(buf), stdin) != NULL)
      {
        i = strtol(buf, &p, 10);
    
        if (buf[0] != '\n' && (*p == '\n' || *p == '\0'))
          printf ("Valid number of %ld entered\n", i); 
        else  printf ("Invalid number entered\n");
      }
    If the user enter 91234567890 that will not be the desirable result becuase the value is bigger long maximum value.

    Is there anything I can do to avoid this problem?

    Many thanks....

  2. #2
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    http://www.hmug.org/man/3/strtol.php

    Code:
    The strtol(), strtoll(), strtoimax() and strtoq() functions return the
         result of the conversion, unless the value would underflow or overflow.
         If no conversion could be performed, 0 is returned and the global vari-
         able errno is set to EINVAL.  If an overflow or underflow occurs, errno
         is set to ERANGE and the function return value is clamped according to
         the following table.
    
               Function       overflow    underflow
               strtol()       LONG_MIN    LONG_MAX
               strtoll()      LLONG_MIN   LLONG_MAX
               strtoimax()    INTMAX_MIN  INTMAX_MAX
               strtoq()       LLONG_MIN   LLONG_MAX
    Basically, check if errno == ERANGE after calling strtol()
    Last edited by Mr_Miguel; 01-21-2008 at 08:32 AM. Reason: Formatting
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    84
    Excellent INPUT!!!! Thank you very much.

    When using errno in a loop, do I have to asssign it to 0 every round?
    Code:
    for (;;)
    {
        . . .
        errno=0;
        i = strtol(buf, &p, 10);
        if (errno==ERANGE)
            puts("Out of range!");
        else
            break;
    }
    I though errno will be assigned a new value every time I call strtol() but it doesn't, when error occur , errno keeps the error even when a valid input entered after, is that how is suppose to be?

    THANK YOU!!!!

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by salvadoravi View Post
    is that how is suppose to be?

    THANK YOU!!!!
    Yes. errno only gets set when an error happens, not when an error fails to happen. (This way things like assigning a value to i, which works, don't keep you from noticing the error from the call to strtol.)

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The "variable" errno is not guaranteed to be settable - it is commonly implemented as a macro that calls a funciton that returns the value - this is so that errno can be threadsafe.

    It is probably better to do something like this:
    Code:
    if (result == LONG_MAX  || result == LONG_MIN)
    { 
        if (errno == ERANGE)
            ... value out of range 
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    Quote Originally Posted by matsp View Post
    The "variable" errno is not guaranteed to be settable - it is commonly implemented as a macro that calls a funciton that returns the value - this is so that errno can be threadsafe.

    It is probably better to do something like this:
    Code:
    if (result == LONG_MAX  || result == LONG_MIN)
    { 
        if (errno == ERANGE)
            ... value out of range 
    }
    --
    Mats
    I see... One question, though: what if the user entered LONG_MAX or LONG_MIN as a value, after errno has been set to ERANGE by a previous iteration? Should we "sacrifice" those two values in order to ensure we're not misusing "errno"?
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sorry, I'm wrong - errno is guaranteed "to be a modifiable lvalue", so yes, you can set it to zero if you like. [It may still be a function call, for example
    Code:
    extern int *ferrno();
    #define errno *ferrno()
    would do that. ]

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Can you set errno to zero prior to the strtol() call?

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    84
    Thank you again guys, great words!!!

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Todd Burch View Post
    Can you set errno to zero prior to the strtol() call?
    Yes, that's the suggested solution.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by matsp View Post
    The "variable" errno is not guaranteed to be settable - it is commonly implemented as a macro that calls a funciton that returns the value - this is so that errno can be threadsafe.

    --
    Mats
    I don't know if it was different in C89, but C99 says this:
    Quote Originally Posted by C99 Standard, 7.5 Paragraph 2
    The macros are
    EDOM
    EILSEQ
    ERANGE
    which expand to integer constant expressions with type int, distinct positive values, and
    which are suitable for use in #if preprocessing directives; and
    errno
    which expands to a modifiable lvalue that has type int, the value of which is set to a
    positive error number by several library functions. It is unspecified whether errno is a
    macro or an identifier declared with external linkage.
    So at least in newer implementations, errno should be settable. In fact, footnote 170 states that a program that wishes to check errno should set it to zero before the library call, and check it afterwards.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by tabstop View Post
    So at least in newer implementations, errno should be settable. In fact, footnote 170 states that a program that wishes to check errno should set it to zero before the library call, and check it afterwards.
    I don't think it's changed any time real recently, I was just confusing it with the fact that you should not declare errno as a variable, as that CAN certainly make a mess of things.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. time limit for user input
    By dudeomanodude in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 03:01 PM
  3. Replies: 4
    Last Post: 04-03-2008, 09:07 PM
  4. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  5. Replies: 4
    Last Post: 04-21-2004, 04:18 PM