我怎么知道c函数atoi失败了,还是它是一串0 ?

时间:2021-12-24 07:21:51

When using the function atoi (or strtol or similar functions for that matter), how can you tell if the integer conversion failed or if the C-string that was being converted was a 0?

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

For what I'm doing, 0 is an acceptable value and the C-string being converted may contain any number of 0s. It may also have leading whitespace.

对于我所做的,0是一个可接受的值,C-string被转换可能包含任何数的0。它也可能有领先的空格。

6 个解决方案

#1


7  

For C++11 and later:

The go-to function for string-to-integer conversion is now stoi, which takes a string and returns an int, or throws an exception on error.

对于string-to-integer转换的go-to函数现在是stoi,它接受一个字符串并返回int,或者抛出异常。

No need for the verbose istringstream hack mentioned in the accepted answer anymore.

不再需要在已接受的答案中提到的冗长的istringstream hack。

(There's also stol/stoll/stof/stod/stold for long/long long/float/double/long double conversions, respectively.)

(也有短距/短距/短距/短距/短距/短距/长距/浮动/双长双距转换。)

#2


41  

The proper function (as long as you are insisting on using C-style functions) is strtol and the conversion code might look as follows

适当的函数(只要你坚持使用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` */

Some remarks:

一些评论:

strtol allows (meaning: quietly skips) whitespace in front of the actual number. If you what to treat such leading whitespace as an error, you have to check for it yourself.

strtol允许(意思是:悄悄跳过)在实际数字前面的空格。如果您认为这样的领先空格是错误的,您必须自己检查它。

The check for *end != '\0' makes sure that there's nothing after the digits. If you want to permit other characters after the actual number (whitespace?), this check has to be modified accordingly.

检查*end != '\0'确保数字后面没有任何东西。如果您想在实际数字之后允许其他字符(空格?),则必须相应地修改此检查。

P.S. I added the end == number check later to catch empty input sequences. "All whitespace" and "no number at all" inputs would have been caught by *end != '\0' check alone. It might make sense to catch empty input in advance though. In that case end == number check will/might become unnecessary.

我添加了end == = number check以捕获空的输入序列。“所有空格”和“no number at All”的输入只会被*end捕获!= '\0' check单独捕获。不过,提前捕获空输入可能是有意义的。在这种情况下,end == = number检查将/可能不再需要。

#3


22  

Since this is tagged :

因为它被标记为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; 
}

#4


5  

From the man page for strtol():

strtol()的man页面:

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, however, strtol() stores the original value of nptr in *endptr. (Thus, if *nptr is not '\0' but **endptr is '\0' on return, the entire string was valid.)

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

#5


2  

An alternative to strtol is sscanf, although it's a little heavy-weight:

另一种选择是sscanf,尽管它有点重:

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

However, this allows leading whitespace in your string (which may or may not be desirable), and it allows anything to trail the number, so "123abc" would be accepted and return 123. If you want to have tighter control, go with strtol(), as AndreyT demonstrates.

但是,这允许字符串中的前导空格(可能需要,也可能不需要),并且允许任何东西跟踪这个数字,因此“123abc”将被接受并返回123。如果您想要更严格的控制,可以使用strtol(),正如AndreyT所演示的那样。

#6


1  

It's been a while since I've done and C/C++, but it would appear to me that the (overly) simple solution would be to check just the string for "0".

我已经有一段时间没有使用C/ c++了,但是在我看来,(过于简单的)解决方案是检查字符串是否为“0”。

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

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}

#1


7  

For C++11 and later:

The go-to function for string-to-integer conversion is now stoi, which takes a string and returns an int, or throws an exception on error.

对于string-to-integer转换的go-to函数现在是stoi,它接受一个字符串并返回int,或者抛出异常。

No need for the verbose istringstream hack mentioned in the accepted answer anymore.

不再需要在已接受的答案中提到的冗长的istringstream hack。

(There's also stol/stoll/stof/stod/stold for long/long long/float/double/long double conversions, respectively.)

(也有短距/短距/短距/短距/短距/短距/长距/浮动/双长双距转换。)

#2


41  

The proper function (as long as you are insisting on using C-style functions) is strtol and the conversion code might look as follows

适当的函数(只要你坚持使用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` */

Some remarks:

一些评论:

strtol allows (meaning: quietly skips) whitespace in front of the actual number. If you what to treat such leading whitespace as an error, you have to check for it yourself.

strtol允许(意思是:悄悄跳过)在实际数字前面的空格。如果您认为这样的领先空格是错误的,您必须自己检查它。

The check for *end != '\0' makes sure that there's nothing after the digits. If you want to permit other characters after the actual number (whitespace?), this check has to be modified accordingly.

检查*end != '\0'确保数字后面没有任何东西。如果您想在实际数字之后允许其他字符(空格?),则必须相应地修改此检查。

P.S. I added the end == number check later to catch empty input sequences. "All whitespace" and "no number at all" inputs would have been caught by *end != '\0' check alone. It might make sense to catch empty input in advance though. In that case end == number check will/might become unnecessary.

我添加了end == = number check以捕获空的输入序列。“所有空格”和“no number at All”的输入只会被*end捕获!= '\0' check单独捕获。不过,提前捕获空输入可能是有意义的。在这种情况下,end == = number检查将/可能不再需要。

#3


22  

Since this is tagged :

因为它被标记为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; 
}

#4


5  

From the man page for strtol():

strtol()的man页面:

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, however, strtol() stores the original value of nptr in *endptr. (Thus, if *nptr is not '\0' but **endptr is '\0' on return, the entire string was valid.)

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

#5


2  

An alternative to strtol is sscanf, although it's a little heavy-weight:

另一种选择是sscanf,尽管它有点重:

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

However, this allows leading whitespace in your string (which may or may not be desirable), and it allows anything to trail the number, so "123abc" would be accepted and return 123. If you want to have tighter control, go with strtol(), as AndreyT demonstrates.

但是,这允许字符串中的前导空格(可能需要,也可能不需要),并且允许任何东西跟踪这个数字,因此“123abc”将被接受并返回123。如果您想要更严格的控制,可以使用strtol(),正如AndreyT所演示的那样。

#6


1  

It's been a while since I've done and C/C++, but it would appear to me that the (overly) simple solution would be to check just the string for "0".

我已经有一段时间没有使用C/ c++了,但是在我看来,(过于简单的)解决方案是检查字符串是否为“0”。

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

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}