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

时间:2009-06-22 09:07:31

标签: 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;
}

这将产生以下输出。

  

数字:7

     

digit2:2147483647

     

digit3:57230

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

编辑:这是否可以接受?

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

5 个答案:

答案 0 :(得分:5)

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

From the atoi reference.

  

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

2147483647是INT_MAX

答案 1 :(得分:5)

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

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

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

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

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

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

此行获取指向位置12的字符串的指针。atoi的参数是字符串 “57230”。这正确地转换为整数57230。

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

...     }

由于您使用的是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)));

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

答案 2 :(得分:3)

bigNumber.at()不返回带有单个字符的新字符串,而是返回字符串中字符的地址。所以第二个电话实际上是:

atoi("720394857230")

导致内部算法溢出。

此外,第一次调用非常危险,因为它取决于(&tmp)+1内存中的(随机)值。

您必须分配一个包含两个字符的字符串,将bigNumber.at()中的单个字符分配给第一个字符,将\0分配给第二个字符,然后使用临时字符串的地址调用atoi()

答案 3 :(得分:3)

atoi的参数应该是一个以零结尾的字符串。

答案 4 :(得分:3)

函数at给出字符串中char的指针。函数atoi将字符串转换为int,而不仅仅是一个字符。