题
当使用函数 atoi
(或 strtol
或类似函数)时,如何判断整数转换是否失败或者是否是C字符串被转换的是 0
?
对于我正在做的事情, 0
是可接受的值,被转换的C字符串可以包含任意数量的 0
。它也可能有领先的空白。
解决方案
对于C ++ 11及更高版本:
字符串到整数转换的转到函数现在是 stoi
,它接受字符串
并返回 int
,或者在出错时抛出异常。
不再需要在接受的答案中提及详细的 istringstream
hack。
(还有 stol
/ stoll
/ stof
/ stod
/ stold
对于 long
/ long long
/ float
/ double
/ long double
转换。)
其他提示
正确的功能(只要你坚持使用C风格的函数)是 strtol
,转换代码可能如下所示
const char *number = "10"; /* for example */
char *end;
long value = strtol(number, &end, 10);
if (end == number || *end != '\0' || errno == ERANGE)
/* ERROR, abort */;
/* Success */
/* Add whatever range checks you want to have on the value of `value` */
一些评论:
strtol
允许(意思是:悄悄地跳过)实际数字前面的空格。如果您将此类前导空格视为错误,则必须自行检查。
检查 * end!='\ 0'
确保数字后面没有任何内容。如果要在实际数字(空格?)之后允许其他字符,则必须相应地修改此检查。
P.S。我稍后添加 end == number
检查以捕获空输入序列。 “所有空白”和“根本没有数字”输入将被 * end!='\ 0'
单独检查。尽管提前捕获空输入可能是有意义的。在这种情况下, end == number
检查将/可能变得不必要。
由于这是标记的 c ++ :
template< typename T >
inline T convert(const std::string& str)
{
std::istringstream iss(str);
T obj;
iss >> std::ws >> obj >> std::ws;
if(!iss.eof())
throw "dammit!";
return obj;
}
来自strtol()的手册页:
如果endptr不为NULL,则strtol()存储第一个无效的地址 * endptr中的字符。但是,如果根本没有数字,strtol() 将nptr的原始值存储在* endptr中。 (因此,如果* nptr不是
'\ 0'
但返回时** endptr为'\ 0'
,整个字符串都有效。)
strtol
的替代方法是 sscanf
,虽然它有点重量级:
const char *numStr = "12345"; // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
; // parsing succeeded, use value
else
; // error
然而,这允许你的字符串中的前导空格(这可能是也可能不是所希望的),并且它允许任何东西跟踪数字,因此“123abc”如果您想要更严格的控制,请使用 strtol()
,作为 AndreyT演示。
自从我完成了C / C ++已经有一段时间了,但在我看来(过于简单)的解决方案就是只检查字符串中的“0”。
int value = atoi(string_number.c_str());
if ( !value && string_number != "0" ) {
// error
} else {
// great success!
}