我已经习惯使用 strtod
和其变种。
我在想为什么 <stdlib.h>
没有提供 strtoi
?
为什么整数类型被排除在这个函数族之外呢?
具体地,我想问为什么没有一个带有 strtod
的安全特性的 atoi
版本?
为什么stdlib.h中没有strtoi函数?
并非必需。
早期的C语言没有标准的有符号整数类型比long
更宽,所有较窄的转换(如int
)都可以使用strtol()
来完成,就像下面所做的那样。
这些函数及其无符号对应函数现在缺失于C标准库(C17/18),这是当前标准库设计上的缺陷。
在许多系统中,long
和int
具有相同的范围,因此不需要单独的strtoi()
。 atoi()
可以填补将字符串转换为int
的快速且简便的代码需求,但可能缺乏错误检测。 在出现错误时,atoi()
会产生未定义行为(UB)。 还没有strto_short()
或 strto_signchar()
等函数。
很容易创建一个替代strtoi()
。 存在简化方式。
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
static long str2subrange(const char *s, char **endptr, int base,
long min, long max) {
long y = strtol(s, endptr, base);
if (y > max) {
errno = ERANGE;
return max;
}
if (y < min) {
errno = ERANGE;
return min;
}
return y;
}
// OP's goal
int str2i(const char *s, char **endptr, int base) {
#if INT_MAX == LONG_MAX && INT_MIN == LONG_MIN
return (int) strtol(s, endptr, base);
#else
return (int) str2subrange(s, endptr, base, INT_MIN, INT_MAX);
#endif
}
short str2short(const char *s, char **endptr, int base) {
return (short) str2subrange(s, endptr, base, SHRT_MIN, SHRT_MAX);
}
signed char str2schar(const char *s, char **endptr, int base) {
return (signed char) str2subrange(s, endptr, base, SCHAR_MIN, SCHAR_MAX);
}
#include <stdint.h>
int16_t str2int16(const char *s, char **endptr, int base) {
return (int16_t) str2subrange(s, endptr, base, INT16_MIN, INT16_MAX);
}
[2021年编辑]
为了避免与未来的库方向发生冲突,名称已从strto...()
更改为str2...()
。
2
表示to
。
<string.h>
头文件的声明中可能会添加以str
、mem
或wcs
和小写字母开头的函数名称。C17dr § 7.31.13 1
strtol()
将一个字符串转换为整数,长整数但仍然是整数。虽然有atoi()
函数,但由于缺乏从无效输入报告错误的机制,大多数情况下应该避免使用它。
long
的范围超过int
的范围时,strtol()
不会设置errno
,也不会在int
上返回INT_MIN/MAX
,只会溢出并取相反数,这可能会破坏该安全功能。 - chux - Reinstate Monicastrtol()
来将字符串转换为 int
,需要指出表示超出 int
范围(但不是 long
)的字符串不会设置 errno
也不会得到限制的值。这与表示超出 long
范围的字符串的行为不同:后者会设置 errno
并获得一个有限的值。 - chux - Reinstate Monicalong
的宽度确实是64位,而int
只有32位,因此范围在[2^31; 2^63)
或其负数对应值[-2^63, -2^31)
内的任何值都需要对int
产生错误,但实际上并没有... - Aconcagualong long_val;
int int_value;
errno = 0;
long_val = strtol (theString, NULL, 10);
if (errno)
handle_error;
if ((long) someIntMin > long_val || long_val > (long) someIntMax)
handle_invalid;
int_value = (int) long_val;
(long)
的强制转换。看起来不必要。 - chux - Reinstate Monicastrtol
,可以将字符串转换为 long
类型,也就是整数类型。int
类型。 - xdavidliuSEE ALSO
部分 :)
SEE ALSO
atof(3), atoi(3), atol(3), strtol(3), strtoul(3)
你需要使用atoi(3)
函数。 :)atoi
。 - James McNellisatoi
返回 0
、INT_MIN
或 INT_MAX
,你就无法知道转换是否成功。 - James McNellisatoi
函数理论上几乎和使用 gets
函数一样糟糕:除非你对输入有非常严格的控制,否则它会导致 未定义行为。幸运的是,大多数实现并没有采取这种自由,而是在溢出时简单地产生类似于 unsigned
的包装,但你不应该依赖这一点。所以不要使用 atoi
函数。 - R.. GitHub STOP HELPING ICE
long, int
。很多(我怀疑约20%)具有32位long
和16位int
。 - chux - Reinstate Monica