C语言 atoi vs atol vs strtol vs strtoul vs sscanf

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22865622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:58:24  来源:igfitidea点击:

atoi vs atol vs strtol vs strtoul vs sscanf

c

提问by user3362954

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

我试图从正在解析的命令行中找出哪个函数最适合将十进制、十六进制或八进制数转换int为最佳数 - 无需事先知道输入。

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:

然后的目标是使用单个函数来识别不同类型的输入并将其分配给它的整数 ( int) 值,然后可以使用它:

./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?

附带问题,这对于将字符串转换为整数是否稳定以供使用?

回答by chux - Reinstate Monica

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

哪个函数最适合将十进制、十六进制或八进制数转换int为最佳 (?)

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.

要将此类文本转换为int,建议long strtol(const char *nptr, char **endptr, int base);在转换为 时进行额外测试int(如果需要)。

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

使用0作为base评估操舵变换早字符作为基体10,16或8 @Mike霍尔特

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 vs atol vs strtol vs strtoul vs sscanf ...到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.

atoi()
专家:非常简单。
优点:转换为int.
优点:在 C 标准库中。
亲:快。
缺点:没有错误处理。
缺点:既不处理十六进制也不处理八进制。

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

atol()
亲:简单。
优点:在 C 标准库中。
亲:快。
Con:转换为long,而不是int大小可能不同的 。
缺点:没有错误处理。
缺点:既不处理十六进制也不处理八进制。

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 intwhich may differ in size.

strtol()
亲:简单。
优点:在 C 标准库中。
优点:良好的错误处理。
亲:快。
优点:可以处理二进制。
Con:转换为long,而不是int大小可能不同的 。

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 intwhich may differ in size.

strtoul()
亲:简单。
优点:在 C 标准库中。
优点:良好的错误处理。
亲:快。
优点:可以处理二进制。
---:似乎不会抱怨负数。
Con:转换为unsigned long,而不是int大小可能不同的 。

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).

sscanf(..., "%i", ...)
优点:在 C 标准库中。
优点:转换为int.
---:中间的复杂性。
缺点:可能很慢。
缺点:OK 错误处理(未定义溢出)。

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

所有人都从locale设置中受益/受益。第 7.22.1.4 节 6 “在除“C”语言环境之外,可以接受其他特定于语言环境的主题序列形式。”



Additional credits:
@Jonathan Leffler: errnotest against ERANGE, atoi()decimal-only, discussion about errnomulti-thread concern.
@MarianSpeed issue.
@Kevin Library inclusiveness.

附加学分:
@Jonathan Lefflererrno针对ERANGEatoi()仅十进制,关于errno多线程问题的讨论进行测试。
@Marian速度问题。
@Kevin 图书馆的包容性。



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

对于转换shortsigned char等,请考虑strto_subrange()

回答by Jonathan Leffler

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).

如果您关心错误情况,那么考虑strtol()strtoul()(或strtoll()strtoull()来自<stdlib.h>,或可能strtoimax()strtoumax()来自<inttypes.h>)才是明智之举。如果您不关心溢出时的错误条件,则可以使用它们中的任何一个。无论是atoi()也不是atol(),也不sscanf()让你控制,如果值溢出。此外,atoi()也不atol()提供对十六进制或八进制输入的支持(因此实际上您无法使用它们来满足您的要求)。

Note that calling the strtoX()functions is not entirely trivial. You have to set errnoto 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 errnoand the end pointer help you distinguish between them all.

请注意,调用strtoX()函数并非完全无关紧要。errno在调用它们之前必须设置为0,并传递一个指针来获取结束位置,仔细分析才知道发生了什么。请记住,这些函数的所有可能的返回值都是有效的输出,但其中一些也可能表示无效的输入——并且errno结束指针可以帮助您区分它们。

If you need to convert to intafter 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_MINand INT_MAX.

如果你需要转换为int使用读取值后,说,strtoll()你可以检查返回值(存储在一个范围内long long),对在规定的范围<limits.h>intINT_MININT_MAX

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

有关完整详细信息,请参阅我的回答:正确使用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.

请注意,这些函数都不会告诉您使用了哪种转换。您需要自己分析字符串。奇怪的提示:你知道C源代码中没有十进制0吗?当你写时0,你正在写一个八进制常量(因为它的第一个数字是 a 0)。这件琐事没有实际后果。