3 回答
TA贡献1809条经验 获得超8个赞
*scanf()函数系列返回转换后的值的数量。因此,您应该检查以确保sscanf()返回1。 EOF因“输入失败”而ssacnf()返回,这意味着将永不返回EOF。
对于sscanf(),函数必须解析格式字符串,然后解码整数。 atoi()没有那笔开销。两者都遭受以下问题:超出范围的值会导致未定义的行为。
您应该使用strtol()或strtoul()函数,它们可以提供更好的错误检测和检查。他们还会让您知道整个字符串是否已被消耗。
如果需要int,可以随时使用strtol(),然后检查返回的值以查看它是否位于INT_MIN和之间INT_MAX。
TA贡献1842条经验 获得超12个赞
如果不用担心无效的字符串输入或范围问题,请使用最简单的方法: atoi()
否则,具有最佳错误/范围检测的方法既不是也不atoi()是sscanf()。 这很好的答案都准备好了细节上缺乏错误检查atoi()和一些错误检查sscanf()。
strtol()是将字符串转换为的最严格的函数int。但这仅仅是一个开始。下面是详细的示例,以显示正确的用法,并在被接受后给出此答案的原因。
// Over-simplified use
int strtoi(const char *nptr) {
int i = (int) strtol(nptr, (char **)NULL, 10);
return i;
}
就像这样atoi(),忽略了使用的错误检测功能strtol()。
要充分利用strtol(),需要考虑多种功能:
检测到没有转换:示例:"xyz"或""或"--0"?在这些情况下,endptr将匹配nptr。
char *endptr;
int i = (int)strtol(nptr, &endptr, 10);
if (nptr == endptr) return FAIL_NO_CONVERT;
整个字符串应该转换还是仅转换开头部分:"123xyz"可以吗?
char *endptr;
int i = (int)strtol(nptr, &endptr, 10);
if (*endptr != '\0') return FAIL_EXTRA_JUNK;
检测是否值这么大,结果不表示为一个long样"999999999999999999999999999999"。
errno = 0;
long L = strtol(nptr, &endptr, 10);
if (errno == ERANGE) return FAIL_OVERFLOW;
检测该值是否在than的范围之外int,但不是long。如果int和long具有相同的范围,则不需要此测试。
long L = strtol(nptr, &endptr, 10);
if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW;
某些实现超出了C标准,并errno出于其他原因进行了设置,例如在未执行转换的情况下将errno设置为EINVAL或EINVAL Base参数的值无效。。测试这些errno值的最佳时间取决于实现。
全部放在一起:(根据您的需要进行调整)
#include <errno.h>
#include <stdlib.h>
int strtoi(const char *nptr, int *error_code) {
char *endptr;
errno = 0;
long i = strtol(nptr, &endptr, 10);
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (errno == ERANGE || i > INT_MAX || i < INT_MIN) {
errno = ERANGE;
i = i > 0 : INT_MAX : INT_MIN;
*error_code = FAIL_INT_OVERFLOW;
}
#else
if (errno == ERANGE) {
*error_code = FAIL_OVERFLOW;
}
#endif
else if (endptr == nptr) {
*error_code = FAIL_NO_CONVERT;
} else if (*endptr != '\0') {
*error_code = FAIL_EXTRA_JUNK;
} else if (errno) {
*error_code = FAIL_IMPLEMENTATION_REASON;
}
return (int) i;
}
注意:提到的所有功能都允许前导空格,可选的前导符号字符,并受语言环境更改的影响。需要更多代码才能进行更严格的转换。
注意:非OP标题更改偏重于重点。此答案更好地适用于原始标题“将字符串转换为整数sscanf或atoi”
- 3 回答
- 0 关注
- 1056 浏览
添加回答
举报