我的 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
数字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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这或多或少都是可以解释的。
此行将单个字符“5”复制到字符变量中。
atoi
将正确转换它。atoi
期望字符串参数是有效的以 0 结尾的字符串。&tmp
只是指向字符变量的指针 - 此调用的行为未定义,因为紧跟在内存中的字符后面的内存未知。 确切地说,您必须创建一个以 null 结尾的字符串并将其传入。*该行获取指向字符串中位置 5 的字符的指针。 这恰好是指向上面原始大数字字符串的指针 - 因此 atoi 的字符串参数看起来像字符串“5720394857230”。 atoi 显然会溢出尝试将其转换为整数,因为没有 32 位整数可以保存它。
该行在位置 12 处获取指向字符串的指针。
atoi
的参数是字符串“57230”。 这已正确转换为整数 57230。
...
由于您使用的是 C++,因此
有更好的方法将字符串转换为整数。 我偏爱的一个是 Boost lexical_cast 库。 您可以这样使用它:
* 严格来说,
atoi
将扫描数字字符,直到找到非数字字符。 显然没有定义何时找到一个以及在读取无效内存位置时会做什么。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.我知道为什么显示第二个数字。
来自 atoi 参考。
2147483647 是 INT_MAX
I know why the 2nd number is displayed.
From the atoi reference.
2147483647 is INT_MAX
bigNumber.at()
不返回包含单个字符的新字符串,而是返回字符串中字符的地址。 所以第二次调用实际上是:导致内部算法溢出。
此外,第一次调用非常危险,因为它取决于
(&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: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.atoi 的参数应该是一个以零结尾的字符串。
The argument to
atoi
should be a zero-terminated string.函数
at
给出指向字符串中 char 的指针。 函数atoi
将字符串转换为int,而不仅仅是一个字符。Function
at
gives pointer to char in the string. Functionatoi
converts string to int, not only one char.