我的atoi()调用之间有什么区别?

Luc*_*cas 1 c++ atoi

我有一个大数字存储在一个字符串中,并试图提取一个数字.但这些电话之间有什么区别?

#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;
}
Run Code Online (Sandbox Code Playgroud)

这将产生以下输出.

数字:7

digit2:2147483647

digit3:57230

第一个是期望的结果.在我看来,第二个是随机数,我在字符串中找不到.第三个是字符串的结尾,但不仅仅是我预期的一个数字,而是从第12个索引到字符串结尾.有人可以向我解释不同的输出吗?

编辑:这是一个可接受的解决方案吗?

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

Óla*_*age 5

我知道为什么会显示第二个号码.

来自atoi参考.

如果正确的值超出可表示值的范围,INT_MAX则返回INT_MIN.

2147483647是INT_MAX


180*_*ION 5

这或多或少都是可以解释的.

int main(){
    std::string bigNumber = "93485720394857230";
Run Code Online (Sandbox Code Playgroud)

该行将单个字符'5'复制到字符变量中.atoi将正确转换. atoi期望string参数是有效的0终止字符串.&tmp只是一个指向字符变量的指针 - 这个调用的行为是未定义的,因为紧跟在内存中字符后面的内存是未知的.确切地说,您必须创建一个以null结尾的字符串并将其传递给.*

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
Run Code Online (Sandbox Code Playgroud)

该行获取指向字符串中位置5的字符的指针.这恰好是指向上面原始大数字字符串的指针 - 所以字符串参数atoi看起来像字符串"5720394857230".atoi显然会过度尝试将其转换为整数,因为没有32位整数将保持这个.

    int digit2 = atoi(&bigNumber.at(5))
Run Code Online (Sandbox Code Playgroud)

该行获取指向位置12的字符串的指针.参数to atoi是字符串"57230".这正确地转换为整数57230.

    int digit3 = atoi(&bigNumber.at(12));
Run Code Online (Sandbox Code Playgroud)

...}

由于您使用的是C++,因此有更好的方法可以将字符串转换为整数.我偏爱的是Boost lexical_cast库.你会像这样使用它:

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)));
Run Code Online (Sandbox Code Playgroud)

*严格来说,atoi将扫描数字字符,直到找到非数字字符.当它找到一个以及在读取无效的内存位置时它将会做什么时,它显然是未定义的.