41

使用该函数atoi(或strtol类似的函数)时,如何判断整数转换是否失败,或者被转换的 C 字符串是否为0?

对于我正在做的事情,0是一个可接受的值,并且正在转换的 C 字符串可能包含任意数量的0s。它也可能有前导空格。

4

6 回答 6

48

正确的函数(只要您坚持使用 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'确保数字后面没有任何内容。如果您想在实际数字(空格?)之后允许其他字符,则必须相应地修改此检查。

PS我end == number稍后添加了检查以捕获空输入序列。“所有空格”和“根本没有数字”输入将仅通过*end != '\0'检查来捕获。不过,提前捕获空输入可能是有意义的。在这种情况下,end == number检查将/可能变得不必要。

于 2009-10-28T23:30:00.890 回答
23

由于这被标记为

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; 
}
于 2009-10-28T23:21:05.637 回答
14

对于 C++11 及更高版本:

字符串到整数转换的首选函数是 now stoi,它接受 astring并返回 a int,或者在出错时抛出异常。

不再需要istringstream接受的答案中提到的冗长黑客攻击。

(还有stol/ stoll/ stof/ stod/分别stold用于long/ long long/ float/ double/long double转换。)

于 2015-02-14T18:47:32.927 回答
6

从 strtol() 的手册页:

如果 endptr 不为 NULL,strtol() 将第一个无效字符的地址存储在 *endptr 中。但是,如果根本没有数字,strtol() 会将 nptr 的原始值存储在 *endptr 中。(因此,如果 *nptr 不是 '\0'但 **endptr'\0'在返回时,整个字符串是有效的。)

于 2009-10-28T23:13:04.687 回答
2

自从我完成 C/C++ 以来已经有一段时间了,但在我看来,(过于)简单的解决方案是只检查字符串中的“0”。

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
于 2009-10-28T23:26:16.760 回答
2

strtolis的替代方案sscanf,尽管它有点重量级:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

但是,这允许在您的字符串中使用前导空格(这可能是可取的,也可能不是可取的),并且它允许任何内容尾随数字,因此“123abc”将被接受并返回 123。如果您想要更严格的控制,请使用strtol(),正如AndreyT 演示的那样。

于 2009-10-29T00:23:25.483 回答