【发布时间】:2011-08-10 08:41:43
【问题描述】:
我正在寻找将字符串转换为stdint.h 整数的标准函数,例如
int i = atoi("123");
unsigned long ul = strtoul("123", NULL, 10);
uint32_t n = mysteryfunction("123"); // <-- ???
【问题讨论】:
标签: c type-conversion c99 stdint
我正在寻找将字符串转换为stdint.h 整数的标准函数,例如
int i = atoi("123");
unsigned long ul = strtoul("123", NULL, 10);
uint32_t n = mysteryfunction("123"); // <-- ???
【问题讨论】:
标签: c type-conversion c99 stdint
有两个常规选项:strto[iu]max,然后检查值是否适合较小的类型,或切换到 sscanf。 C 标准在<inttypes.h> 中定义了一整套宏,这些宏扩展为<stdint.h> 类型的适当转换说明符。 uint32_t 的示例:
#include <inttypes.h>
#include <stdio.h>
int main()
{
uint32_t n;
sscanf("123", "%"SCNu32, &n);
printf("%"PRIu32"\n", n);
return 0;
}
(在uint32_t、strtoul的情况下,+溢出检查也适用于uint32_t,因为unsigned long至少有32位宽。它不能可靠地用于uint_least32_t、uint_fast32_t ,uint64_t 等)
编辑:正如 Jens Gustedt 在下面指出的那样,这并不能提供 strtoul 的全部灵活性,因为您无法指定基数。但是,base 8 和 base 16 仍然可以分别用SCNo32 和SCNx32 获得。
【讨论】:
SCNo32 处理基数 8,SCNx32 基数 16;所以只有奇异的基础和二进制没有被覆盖,二进制实现起来很简单。
strtouxxx 允许您指定0 的底数,在这种情况下,它是从数字推断出来的(通过解释它作为一个整数常量),如果您想允许(比如说)某人同时使用十六进制和十进制,这将非常有用。当然,结束指针有时也非常非常有用。
scanf 也有你的力量。只需使用%i 代替%d、%o、%x 等。
%i 是用于signed 目标对象,但不能简单地用于替换strtoul。
由于您的问题涉及unsigned 整数,因此溢出检查很简单。带一点辅助功能
inline
unsigned long long
strtoullMax(const char *nptr,
char **endptr,
int base,
unsigned long long maxval) {
unsigned long long ret = strtoll(nptr, endptr, base);
if (ret > maxval) {
ret = maxval;
errrno = ERANGE;
} else {
if (ret == ULLONG_MAX && errno == ERANGE)
ret = maxval;
}
return ret;
}
您可以轻松地为您感兴趣的任何类型定义宏
#define strtou32(NPTR, ENDPTR, BASE) \
strtoullMax(NPTR, ENDPTR, BASE, (uint32_t)-1)
#define strtou32f(NPTR, ENDPTR, BASE) \
strtoullMax(NPTR, ENDPTR, BASE, (uint_fast32_t)-1)
#define strtou32l(NPTR, ENDPTR, BASE) \
strtoullMax(NPTR, ENDPTR, BASE, (uint_least32_t)-1)
【讨论】:
uintmax_t 和strtoumax,因为strtoumaxmax 太尴尬了;)?那些更安全,因为 IIRC 不能保证 uint_{fast,least}32_t 会小于 unsigned long long,而根据定义它们小于或等于 uintmax_t。