What is difference between my atoi() calls?

2019-08-06 17:52发布

I have a big number stored in a string and try to extract a single digit. But what are the differences between those calls?

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

This will produce the following output.

digit: 7

digit2: 2147483647

digit3: 57230

The first one is the desired result. The second one seems to me to be a random number, which I cannot find in the string. The third one is the end of the string, but not just a single digit as I expected, but up from the 12th index to the end of the string. Can somebody explain the different outputs to me?

EDIT: Would this be an acceptable solution?

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;

标签: c++ atoi
5条回答
Root(大扎)
2楼-- · 2019-08-06 18:29

The argument to atoi should be a zero-terminated string.

查看更多
beautiful°
3楼-- · 2019-08-06 18:32

I know why the 2nd number is displayed.

From the atoi reference.

If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.

2147483647 is INT_MAX

查看更多
趁早两清
4楼-- · 2019-08-06 18:44

It is all more or less explicable.

int main(){
    std::string bigNumber = "93485720394857230";

This line copies the single character '5' into the character variable. atoi will convert this correctly. atoi expects that the string parameter is a valid 0 terminated string. &tmp is only a pointer to the character variable - the behaviour of this call is undefined since the memory immediately following the character in memory is unknown. To be exact, you would have to create a null terminated string and pass that in.*

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

This line gets a pointer to the character in position 5 in the string. This happens to be a pointer into the original big number string above - so the string parameter to atoi looks like the string "5720394857230". atoi will clearly oveflow trying to turn this into an integer since no 32 bit integer will hold this.

    int digit2 = atoi(&bigNumber.at(5))

This line gets a pointer into the string at position 12. The parameter to atoi is the string "57230". This is converted into the integer 57230 correctly.

    int digit3 = atoi(&bigNumber.at(12));

... }

Since you are using C++, there are nicer methods to convert strings of characters into integers. One that I am partial to is the Boost lexical_cast library. You would use it like this:

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

* Strictly, atoi will scan through the numeric characters until a non-numeric one is found. It is clearly undefined when it would find one and what it will do when reading over invalid memory locations.

查看更多
一纸荒年 Trace。
5楼-- · 2019-08-06 18:44

Function at gives pointer to char in the string. Function atoi converts string to int, not only one char.

查看更多
beautiful°
6楼-- · 2019-08-06 18:45

bigNumber.at() doesn't return a new string with a single character but the address of a character in the string. So the second call is actually:

atoi("720394857230")

which causes the internal algorithm to overflow.

Also, the first call is very dangerous since it depends on the (random) value in memory at (&tmp)+1.

You have to allocate a string with two characters, assign the single character from bigNumber.at() to the first and \0 to the second and then call atoi() with the address of the temporary string.

查看更多
登录 后发表回答