【发布时间】:2011-04-17 02:23:09
【问题描述】:
atol() 和 strtol() 有什么区别?
根据他们的手册页,它们似乎具有相同的效果以及匹配的参数:
long atol(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
在一般情况下,当我不想使用base 参数时(我只有十进制数字),我应该使用哪个函数?
【问题讨论】:
atol() 和 strtol() 有什么区别?
根据他们的手册页,它们似乎具有相同的效果以及匹配的参数:
long atol(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
在一般情况下,当我不想使用base 参数时(我只有十进制数字),我应该使用哪个函数?
【问题讨论】:
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).
以下代码检查范围错误。 (稍微修改了 Eli 的代码)
#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;
}
【讨论】:
根据atoi 手册页,它已被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 为您提供了更大的灵活性,因为它实际上可以告诉您整个字符串是否已转换为整数。 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 可能只适用于非常简单和受控的情况。
【讨论】:
if (!*end)。它将指向字符串的空终止符(如果已全部转换),但本身不会设置为 NULL。
simple_strtol?使用您的确切模型,我无法将 if (!*end) 条件评估为真。
0 由atol() 返回以防出错。引用:如果值无法表示,则行为未定义。
atol 功能是strtol 功能的子集,除了atol 不提供任何可用的错误处理功能。 ato... 函数最突出的问题是它们在溢出的情况下会导致未定义的行为。注意:这不仅仅是在发生错误时缺乏信息反馈,这是未定义的行为,即通常是不可恢复的故障。
这意味着atol 函数(以及所有其他ato.. 函数)对于任何严肃的实际用途都毫无用处。这是一个设计错误,它的位置是 C 历史的垃圾场。您应该使用 strto... 组中的函数来执行转换。除其他外,它们被引入以纠正ato... 组功能中固有的问题。
【讨论】:
如果没有记错,strtol() 的额外好处是可以将(可选)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" */
【讨论】:
atol(str) 等价于
strtol(str, (char **)NULL, 10);
如果您想要结束指针(检查是否有更多字符要读取,或者实际上您是否已经读取了任何字符)或不是 10 的基数,请使用 strtol。否则,atol 很好。
【讨论】:
在新代码中,我总是使用strtol。它具有错误处理功能,endptr 参数允许您查看使用了字符串的哪一部分。
C99 标准规定了 ato* 函数:
除了错误的行为,它们等价于
atoi: (int)strtol(nptr,(char **)NULL, 10)atol: strtol(nptr,(char **)NULL, 10)atoll: strtoll(nptr, (char **)NULL, 10)
【讨论】: