atoi vs atol vs strtol vs strtoul vs sscanf
我试图从正在解析的命令行中找出,哪个函数最好将十进制,hex或八进制数转换为最好的int
– 事先不知道输入。
然后,目标是使用一个识别不同类型输入的函数,并将其分配给它的整数( int
)值,然后可以使用它:
./a.out 23 0xC4 070
可以打印
23 196 /*hexadecimal*/ 56 /*octal*/
我能看到的唯一问题是解析找到十进制整数和八进制之间的差异。
边题,这是否可以将字符串转换为整数使用?
哪个函数最好将十进制,hex或八进制数转换为最佳的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 #include #include 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()
亲:简单。
Pro:转换为int
。
Pro:在C标准库中。
亲:快。
Con:没有error handling。
Con:既不处理hex也不处理八进制。
atol()
亲:简单。
Pro:在C标准库中。
亲:快。
Con:转换为long
,而不是int
,其大小可能不同。
Con:没有error handling。
Con:既不处理hex也不处理八进制。
strtol()
亲:简单。
Pro:在C标准库中。
亲:良好的error handling。
亲:快。
Con:转换为long
,而不是int
,其大小可能不同。
strtoul()
亲:简单。
Pro:在C标准库中。
亲:良好的error handling。
亲:快。
—:似乎没有抱怨负数。
Con:转换为unsigned long
,而不是int
,其大小可能不同。
sscanf(..., "%i", ...)
Pro:在C标准库中。
Pro:转换为int
。
—:中间的复杂性。
骗局:慢。
Con:OKerror handling(未定义溢出)。
所有受到locale
设置的影响/受益。 §7.22.1.46“除”C“语言环境外,可以接受其他特定于语言环境的主题序列表格。”
额外学分:
@Jonathan Leffler : errno
测试针对ERANGE
, atoi()
仅限十进制,关于errno
multithreading关注的讨论。
@Marian Speed问题。
@Kevin图书馆的包容性。
要转换short
, signed char
等,请考虑strto_subrange()
。
如果您关心错误,从
或者strtoimax()
或strtoumax()
考虑strtol()
和strtoul()
(或者strtoll()
或strtoull()
是strtoimax()
条件。 如果您不关心溢出的错误条件,可以使用它们中的任何一个。 atoi()
和atol()
以及sscanf()
都不能控制值是否溢出。 另外, atoi()
和atol()
atoi()
都不支持hex或八进制输入(因此实际上你不能使用它们来满足你的要求)。
请注意,调用strtoX()
函数并非完全无关紧要。 您必须在调用它们之前将errno
为0,并传递指针以获取结束位置,并仔细分析以了解发生了什么。 请记住,这些函数的所有可能返回值都是有效输出,但其中一些也可能表示无效输入 – 而errno
和结束指针可帮助您区分它们。
如果在使用strtoll()
读取值后需要转换为int
,则可以检查返回值的范围(存储在long long
)与
为int
: INT_MIN
定义的范围INT_MAX
。
有关完整的详细信息,请参阅我的答案: 正确使用strtol()
。
请注意,这些函数都不会告诉您使用了哪个转换。 您需要自己分析字符串。 古怪的说明:你知道C源中没有小数0; 当你写0
,你正在写一个八进制常量(因为它的第一个数字是0
)。 这件琐事没有实际的后果。