atol() 和 strtol() 的区别是什么?
根据它们的手册页,它们似乎具有相同的效果和匹配的参数:
long atol(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
在一般情况下,当我不想使用base
参数(我只有十进制数)时,我应该使用哪个函数?
strtol
可以提供更多的灵活性,因为它实际上可以告诉您整个字符串是否被转换为整数。而atol
在无法将字符串转换为数字时(例如atol(“help”)
中),返回0,这与atol(“0”)
无法区分:
int main()
{
int res_help = atol("help");
int res_zero = atol("0");
printf("Got from help: %d, from zero: %d\n", res_help, res_zero);
return 0;
}
输出:
Got from help: 0, from zero: 0
strtol
函数将使用它的endptr
参数来指示转换失败的位置。
int main()
{
char* end;
int res_help = strtol("help", &end, 10);
if (!*end)
printf("Converted successfully\n");
else
printf("Conversion error, non-convertible part: %s", end);
return 0;
}
输出:
Conversion error, non-convertible part: help
因此,对于任何严肃的编程,我强烈建议使用 strtol
。虽然它的使用方法有些棘手,但这是有很好的原因的,正如我上面所解释的那样。atol
只适用于非常简单和可控的情况。atol
函数功能是strtol
的子集,但atol
不提供可用的错误处理能力。 ato...
函数的最突出问题是在溢出的情况下导致未定义行为。注意:这不仅是缺乏错误信息反馈,而是未定义行为,即通常是无法恢复的失败。
这意味着atol
函数(以及所有其他ato..
函数)对于任何严肃的实际用途都几乎没有用处。这是一个设计错误,它的位置应该在C历史的垃圾场上。您应该使用strto...
组中的函数执行转换。它们被引入,主要是为了纠正ato...
组函数固有的问题。
根据atoi
的man页面,它已被strtol
取代。
IMPLEMENTATION NOTES
The atoi() and atoi_l() functions have been deprecated by strtol() and strtol_l()
and should not be used in new code.
strtol
。它具有错误处理功能,并且 endptr
参数允许您查看使用了字符串的哪个部分。ato*
函数的规定如下:
除了错误处理行为外,它们等同于
atoi: (int)strtol(nptr,(char **)NULL, 10)
atol: strtol(nptr,(char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)
atol(str)
相当于将字符串转换为长整型。
strtol(str, (char **)NULL, 10);
如果你想要结束指针(用于检查是否有更多的字符需要读取或者实际上是否已经读取了任何字符)或者使用除10以外的进制,那么请使用strtol。否则,atol就可以了。
strtol()
有个额外的好处是可以设置(可选的)endptr
指向第一个不能被转换的字符。如果endptr
为NULL
,则会被忽略。这样,如果您处理的字符串包含数字和字符的混合,您就可以继续进行处理。例如:char buf[] = "213982 and the rest";
char *theRest;
long int num = strtol(buf, &theRest, 10);
printf("%ld\n", num); /* 213982 */
printf("%s\n", theRest); /* " and the rest" */
strtol的手册给出了以下内容:
ERRORS
EINVAL (not in C99) The given base contains an unsupported value.
ERANGE The resulting value was out of range.
The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
errno = 0;
char* end = 0;
long res = strtol("83459299999999999K997", &end, 10);
if(errno != 0)
{
printf("Conversion error, %s\n", strerror(errno));
}
else if (*end)
{
printf("Converted partially: %i, non-convertible part: %s\n", res, end);
}
else
{
printf("Converted successfully: %i\n", res);
}
return 0;
}
虽然这个问题很老,但内容并不是关于语言的一个重要组成部分。
其他答案未能强调两个重要细节: atol
和 strl
都会做同样的事情,但 atol
仅尝试解析 base 10
格式(符号和数字),并且不会给出错误。
而 strtol
(以及所有返回整数类型的 strto_
)可以在任何从 2 到 36 的基数中获取数字,而所有的 ato_
函数(atoi、atol)只能获取基数为 10 的数字。
如果无法解析,则两者都将返回零(0),但 strtol
可以给出解析结束的位置以及如果数字太大/太小则会出现错误。
附注:任何返回十进制数的 strto_
或 ato_
都使用基数 10,表示浮点数的数字和一些其他字符。
if (!*end)
。它将指向字符串的空终止符(如果全部转换),但本身不会被设置为 NULL。 - Jeff Mercadosimple_strtol
?我无法使用您的确切模型使if (!*end)
条件评估为真。 - boltup_im_codingatol()
出现错误时返回0
。引用:“如果该值无法表示,则行为未定义。” - patryk.beza