atoi vs atol vs strtol vs strtoul vs sscanf

后端 未结 2 1895
情歌与酒
情歌与酒 2020-11-29 22:47

I\'m trying to figure out from a command line being parsed, which function would be best to convert either a decimal, hexadecimal, or octal number to an int the

相关标签:
2条回答
  • 2020-11-29 23:09

    which function would be best to convert either a decimal, hexadecimal, or octal number to an int the best (?)

    To convert such text to int, recommend long strtol(const char *nptr, char **endptr, int base); with additional tests when converting to int, if needed.

    Use 0 as the base to assess early characters in steering conversion as base 10, 16 or 8. @Mike Holt

    0x or 0X followed by hex digits--> hexadecimal  
    0 --> octal  
    else --> decimal  
    

    Sample code

    #include <errno.h>
    #include <limits.h>
    #include <stdlib.h>
    
    int mystrtoi(const char *str) {
      char *endptr;
      errno = 0;
      //                                   v--- determine conversion base
      long long_var = strtol(str, &endptr, 0);
      //   out of range   , extra junk at end,  no conversion at all   
      if (errno == ERANGE || *endptr != '\0' || str == endptr) {
        Handle_Error();
      }
    
      // Needed when `int` and `long` have different ranges
      #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
      if (long_var < INT_MIN || long_var > INT_MAX) {
        errno = ERANGE;
        Handle_Error();
      }
      #endif
    
      return (int) long_var;
    }
    

    atoi vs atol vs strtol vs strtoul vs sscanf ... to int

    atoi()
    Pro: Very simple.
    Pro: Convert to an int.
    Pro: In the C standard library.
    Pro: Fast.
    Con: No error handling.
    Con: Handle neither hexadecimal nor octal.

    atol()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Fast.
    Con: Converts to an long, not int which may differ in size.
    Con: No error handling.
    Con: Handle neither hexadecimal nor octal.

    strtol()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Good error handling.
    Pro: Fast.
    Pro: Can handle binary.
    Con: Convert to an long, not int which may differ in size.

    strtoul()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Good error handling.
    Pro: Fast.
    Pro: Can handle binary.
    ---: Appears to not complain about negative numbers.
    Con: Converts to an unsigned long, not int which may differ in size.

    sscanf(..., "%i", ...)
    Pro: In the C standard library.
    Pro: Converts to int.
    ---: Middle-of-the-road complexity.
    Con: Potentially slow.
    Con: OK error handling (overflow is not defined).

    All suffer/benefit from locale settings. §7.22.1.4 6 “In other than the "C" locale, additional locale-specific subject sequence forms may be accepted.”


    Additional credits:
    @Jonathan Leffler: errno test against ERANGE, atoi() decimal-only, discussion about errno multi-thread concern.
    @Marian Speed issue.
    @Kevin Library inclusiveness.


    For converting short, signed char, etc., consider strto_subrange().

    0 讨论(0)
  • 2020-11-29 23:19

    It is only sensible to consider strtol() and strtoul() (or strtoll() or strtoull() from <stdlib.h>, or perhaps strtoimax() or strtoumax() from <inttypes.h>) if you care about error conditions. If you don't care about error conditions on overflow, any of them could be used. Neither atoi() nor atol() nor sscanf() gives you control if the values overflow. Additionally, neither atoi() nor atol() provides support for hex or octal inputs (so in fact you can't use those to meet your requirements).

    Note that calling the strtoX() functions is not entirely trivial. You have to set errno to 0 before calling them, and pass a pointer to get the end location, and analyze carefully to know what happened. Remember, all possible return values from these functions are valid outputs, but some of them may also indicate invalid inputs — and errno and the end pointer help you distinguish between them all.

    If you need to convert to int after reading the value using, say, strtoll(), you can check the range of the returned value (stored in a long long) against the range defined in <limits.h> for int: INT_MIN and INT_MAX.

    For full details, see my answer at: Correct usage of strtol().

    Note that none of these functions tells you which conversion was used. You'll need to analyze the string yourself. Quirky note: did you know that there is no decimal 0 in C source; when you write 0, you are writing an octal constant (because its first digit is a 0). There are no practical consequences to this piece of trivia.

    0 讨论(0)
提交回复
热议问题