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

发布于 2024-07-25 14:02:08 字数 951 浏览 4 评论 0原文

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

#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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

享受孤独 2024-08-01 14:02:08

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

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

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

    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 将扫描数字字符,直到找到非数字字符。 显然没有定义何时找到一个以及在读取无效内存位置时会做什么。

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.

黑白记忆 2024-08-01 14:02:08

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

来自 atoi 参考。

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

2147483647 是 INT_MAX

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

一生独一 2024-08-01 14:02:08

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

atoi("720394857230")

导致内部算法溢出。

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

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

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.

青柠芒果 2024-08-01 14:02:08

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

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

看海 2024-08-01 14:02:08

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文