Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
620 views
in Technique[技术] by (71.8m points)

c - atoi vs atol vs strtol vs strtoul vs sscanf

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 best — without knowing the input beforehand.

The goal then is to use a single function that recognizes the different types of inputs and assign that to its integer (int) value which can then be used so:

./a.out 23 0xC4 070

could print

23
196 /*hexadecimal*/
56  /*octal*/

The only issue that I can see is the parsing to find the difference between a decimal integer and an octal.

Side question, is this stable for converting the string to an integer for use?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 != '' || 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().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...