关于C#:atoi vs atol vs strtol vs strtoul vs sscanf


atoi vs atol vs strtol vs strtoul vs sscanf

我正在尝试从正在解析的命令行中找出哪个函数最好将十进制,十六进制或八进制数转换为最好的int,而无需事先知道输入。

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

1
./a.out 23 0xC4 070

可以打印

1
2
3
23
196 /*hexadecimal*/
56  /*octal*/

我可以看到的唯一问题是解析,以查找十进制整数和八进制之间的差异。

附带的问题是,将字符串转换为整数以便使用是否稳定?


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

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

使用0作为base,以10、16或8为基数评估转向转换中的早期字符。@Mike Holt

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

样例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#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()
优点:非常简单。
专业版:转换为int
Pro:在C标准库中。
优点:快。
缺点:没有错误处理。
缺点:既不处理十六进制也不处理八进制。

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

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

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

sscanf(...,"%i", ...)
Pro:在C标准库中。
专业版:转换为int
---:复杂的路途。
缺点:可能会变慢。
缺点:可以进行错误处理(未定义溢出)。

所有人都从locale设置中受益/受益。 §7.22.1.46"在" C"语言环境之外,还可以接受其他特定于语言环境的主题序列形式。"

其他学分:
@Jonathan Leffler:errno针对ERANGEatoi()仅十进制的测试,关于errno多线程问题的讨论。
@玛丽安速度问题。
@凯文图书馆的包容性。

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


如果您关心错误情况,仅考虑使用strtol()strtoul()(或中的strtoll()strtoull()中的strtoimax()strtoumax())是明智的。如果您不关心溢出时的错误情况,则可以使用其中任何一个。 atoi()atol()sscanf()都不能控制值是否溢出。此外,atoi()atol()都不支持十六进制或八进制输入(因此,实际上您不能使用它们来满足您的要求)。

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

如果在使用例如strtoll()读取值后需要转换为int,则可以对照中为int定义的范围来检查返回值(存储在long long中)的范围。 :INT_MININT_MAX

有关完整的详细信息,请参见以下答案:strtol()的正确用法。

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