1

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

#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

数字2:2147483647

数字3:57230

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

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

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

5 回答 5

5

我知道为什么显示第二个数字。

来自 atoi 参考。

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

2147483647 是 INT_MAX

于 2009-06-22T09:12:32.930 回答
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 的指针。参数 toatoi是字符串“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将扫描数字字符,直到找到非数字字符。它何时会找到一个以及在读取无效内存位置时会做什么显然是未定义的。

于 2009-06-22T09:13:58.467 回答
3

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

atoi("720394857230")

这会导致内部算法溢出。

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

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

于 2009-06-22T09:12:24.740 回答
3

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

于 2009-06-22T09:12:56.067 回答
3

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

于 2009-06-22T09:13:59.730 回答