你有三种选择:
1. atoi
这可能是最快的方法,如果你在性能关键代码中使用它,但它不提供错误报告。如果字符串不以整数开头,则返回0。如果该字符串包含整数后面的其他字符,则只会转换初始部分并忽略其余部分。如果数字太大而无法适应 int,则行为未指定。
2. sscanf
提供一些错误报告,并且你可以灵活地选择要存储的类型(char/short/int/long/long long/size_t/ptrdiff_t/intmax_t 的有符号/无符号版本)。
返回值是成功转换的次数,因此扫描 "%d" 会返回0,如果字符串不以整数开头。你可以使用 "%d%n" 将读取的整数之后的第一个字符的索引存储在另一个变量中,从而检查是否已将整个字符串转换或是否有其他字符。然而,与 atoi 一样,对于整数溢出的行为是未指定的。
3. strtol 及其相关函数
提供健壮的错误报告,前提是在调用之前将 errno 设置为 0。溢出时指定了返回值,并设置了 errno。你可以选择任何进制数,从2到36,或将基数指定为 0,以自动解释前导 "0x" 和 "0" 分别作为十六进制和八进制。可选的转换类型是 signed/unsigned 版本的 long/long long/intmax_t。
如果需要更小的类型,你可以将结果存储在一个临时的 long 或 unsigned long 变量中,并自行检查溢出。
由于这些函数接受指向指针的参数,因此你还会获得指向转换整数后的第一个字符的指针,从而可以免费获得整个字符串是否为整数或者如果需要解析字符串中的后续数据。
个人而言,我会建议对于大多数情况使用 strtol 系列函数。如果你只是做一些快速简短的事情,atoi 可能满足你的需求。
顺便说一下,在某些情况下,我发现需要解析数字,其中不应接受前导空格、符号等。在这种情况下,编写其自己的 for 循环相当容易。
for (x=0; (unsigned)*s-'0'<10; s++)
x=10*x+(*s-'0');
或者你可以使用以下代码(提高鲁棒性):
if (isdigit(*s))
x=strtol(s, &s, 10);
else /* error */