atoi vs atol vs strtol vs strtoul vs sscanf

时间:2014-04-04 14:30:23

标签: c

我试图从正在解析的命令行中弄清楚,哪个函数最好将十进制,十六进制或八进制数转换为最好的int - 事先不知道输入。< / p>

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

./a.out 23 0xC4 070

可以打印

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

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

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

2 个答案:

答案 0 :(得分:23)

  

哪个函数最好将十进制,十六进制或八进制数转换为最佳的int(?)

要将此类文本转换为int,请在转换为long strtol(const char *nptr, char **endptr, int base);时根据需要推荐int并进行其他测试。

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

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

示例代码

#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

atoi()
亲:很简单。
专业:转换为int Pro:在C标准库中 亲:快。
Con:没有错误处理。
Con:既不处理十六进制也不处理八进制。

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

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

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

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

所有受locale设置影响/受益。 §7.22.1.46“除”C“语言环境外,可以接受其他特定于语言环境的主题序列表格。”


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


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

答案 1 :(得分:11)

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

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

如果您需要在使用int读取值后转换为strtoll(),则可以检查返回值的范围(存储在long long中)与范围相对应在<limits.h>intINT_MININT_MAX定义。

有关详细信息,请参阅我的回答:Correct usage of strtol()

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