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;
The argument to
atoi
should be a zero-terminated string.I know why the 2nd number is displayed.
From the atoi reference.
2147483647 is INT_MAX
It is all more or less explicable.
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.*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.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.... }
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:
* 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.Function
at
gives pointer to char in the string. Functionatoi
converts string to int, not only one char.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: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 callatoi()
with the address of the temporary string.