[英]c++ stoi doesn't convert string correctly
#include <iostream>
#include <string>
int main() {
std::string s = "3a3";
try
{
int i = std::stoi(s);
std::cout << i << '\n';
}
catch (std::invalid_argument const &e)
{
std::cout << "Bad input: std::invalid_argument thrown" << '\n';
}
catch (std::out_of_range const &e)
{
std::cout << "Integer overflow: std::out_of_range thrown" << '\n';
}
return 0;
}
出来的是“3”。 前 3 后有字母表。它是如何转换的......? "10 10" 也是 10。它无法捕捉中间的空格。
快速响应:尝试:
std::stoi(s, nullptr, 16)
解释:
stoi function 有三个参数
您遇到的问题是,如果未提供 base , stoi 将使用其默认值(即 10,并且是最常用的基本格式)。
所以第一个问题是字符“a”不是以 10 为基数的数字,因此会引发 invalid_argument 异常。 第二个问题是由于 stoi 如何处理异常而发生的。 仅当 stoi 无法转换字符串中的任何字符时才会引发异常。 这意味着虽然至少第一个字符是有效数字(考虑到基数),但不会引发异常,而是会返回忽略第一个非基数之后的任何字符的转换。
在这种情况下,“3a3”会在字符“a”处引发异常,因为它不是以 10 为基数的数字。 然后它将转换为 integer 所有先前的字符,在这种情况下,这只是第一个字符“3”,这就是您得到该结果的原因。 不引发异常。 但是,如果字符串是“a33”,则 stoi 将无法转换 'a',因为它不是十进制数字并且会引发异常; 因为它无法转换任何数字。
为避免这种情况,我通常会逐个检查整个字符串是否是有效的数字检查。
std::string myString = "265F"
for(auto ch : myString)
{
if(!isxdigit(ch))
{
throw std::invalid_argument("error message")
}
}
该代码将检查字符串对于十六进制是否有效。 对于十进制数字,您可以使用 isdigit()。
例如,如果您有“327F”,那么stoi("327f")
将返回 327。此外,重要的是要记住 bases 也会更改字符串的值。 例如,十六进制的 10 是十进制的 16。 因此,除十进制以外的任何基数的转换都需要作为参数显式传递。 如果未提供基数,则假定字符串以十进制为基数,十进制的 10 为 10。
您想要的是将基本参数设置为十六进制 (16),然后计算将接受字符 0123456789ABCDEF 和小写变体作为数字。 如果字符串以十六进制而不是十进制为基数写入,这也将返回预期值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.