atoi 函数族和 strtol 函数族都用来将字符串转换成数字。但是具体的区别和联系是什么呢?
通过查看 glibc 的函数源码,可以清楚的看到两者的关系。
两个函数族函数返回类型的对应关系。
返回类型 | atoi函数族 | strol函数族 |
---|---|---|
int | atoi | |
long | atol | strtol |
long long | atoll | strtoll |
float | strtof | |
double | atof | strtod |
函数原型
long atol(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
atoi 函数族的 glibc 实现:
atoi 的 glibc 实现:有一个强制类型转换
/* Convert a string to an int. */
int
atoi (const char *nptr)
{
return (int) strtol (nptr, (char **) NULL, 10);
}
atol 的 glibc 实现
/* Convert a string to a long int. */
long int
atol (const char *nptr)
{
return strtol (nptr, (char **) NULL, 10);
}
atoll 的 glibc 实现
/* Convert a string to a long long int. */
long long int
atoll (const char *nptr)
{
return strtoll (nptr, (char **) NULL, 10);
}
atof 的 glibc 实现
/* Convert a string to a double. */
double
atof (const char *nptr)
{
return strtod (nptr, (char **) NULL);
}
两者的关系说明。
从以上代码可以看出,atoi 函数族是 strtol 函数族的一种特例
。
以 atol 为例
/* Convert a string to a long int. */
long int
atol (const char *nptr)
{
return strtol (nptr, (char **) NULL, 10);
}
通过代码可以看出,atol 只是 strtol 在 10 进制下,且不考虑错误处理的情况下特殊情况。
atol 胜在易用性,但是不能进行其他进制的解析和错误处理。
注意:
虽然,atol 由 strtol实现,因此也会设置 errno,但是 errno 只有以下两种返回值:
- EINVAL (not in C99): 进制值输入错误(支持的进制 [2, 36],即算上字母所能表达的数字范围)
- ERANGE: 结果超出范围
因此不能通过 errno 判断以下情况解析是否正确:
- “abc”
atol 会返回 0,无法判断字符串是 “0” 还是未解析正确。 - “123abc”
atol 会返回 123, 但是后续的 “abc” 将无法继续解析。
strtol 的使用示例
以下示例取自 man strtol 中的示例代码:
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
int base;
char *endptr, *str;
long val;
if (argc < 2) {
fprintf(stderr, "Usage: %s str [base]\n", argv[0]);
exit(EXIT_FAILURE);
}
str = argv[1];
base = (argc > 2) ? atoi(argv[2]) : 10;
errno = 0; /* To distinguish success/failure after call */
val = strtol(str, &endptr, base);
/* Check for various possible errors */
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0)) {
perror("strtol");
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, "No digits were found\n");
exit(EXIT_FAILURE);
}
/* If we got here, strtol() successfully parsed a number */
printf("strtol() returned %ld\n", val);
if (*endptr != '\0') /* Not necessarily an error... */
printf("Further characters after number: %s\n", endptr);
exit(EXIT_SUCCESS);
}