我刚刚发现(令我惊讶的是)以下输入不会导致std::stoi抛出异常:
3.14
3.14helloworld
Run Code Online (Sandbox Code Playgroud)
违反了最小惊喜原则 - 因为这些都不是有效的格式整数值。
请注意,也许更令人惊讶的3.8是转换为值3。
std::stoi当输入确实不是有效整数时,是否有更严格的版本会抛出异常?还是我必须自己动手?
顺便问一下,为什么C++标准库要std::stoi这样实现呢?该函数唯一的实际用途是拼命尝试从随机垃圾输入中获取一些整数值 - 这似乎不是一个非常有用的函数。
这是我的解决方法。
static int convertToInt(const std::string& value)
{
std::size_t index;
int converted_value{std::stoi(value, &index)};
if(index != value.size())
{
throw std::runtime_error("Bad format input");
}
return converted_value;
}
Run Code Online (Sandbox Code Playgroud)
你的问题的答案:
是否有更严格的 std::stoi 版本?
是:不,不在标准库中。
std::stoi,如此处所述的行为类似于 CPP 参考中的解释:
丢弃所有空白字符(通过调用 std::isspace 来识别),直到找到第一个非空白字符,然后采用尽可能多的字符来形成有效的基数 n(其中 n=base)整数表示形式并转换它们为整数值。有效的整数值由以下部分组成: . 。。。。
如果您想要一个更强大的版本来std::stoi满足您的特殊需求,您确实需要编写自己的函数。
有许多潜在的实现,没有一个“正确”的解决方案。这取决于您的需求和编程风格。
我只是向您展示(许多可能的之一)示例解决方案:
#include <iostream>
#include <string>
#include <utility>
#include <regex>
// Some example. Many many other different soultions possible
std::pair<int, bool> stoiSpecial(const std::string s) {
int result{};
bool validArgument{};
if (std::regex_match(s, std::regex("[+-]?[0-9]+"))) {
try {
result = stoi(s);
validArgument = true;
}
catch (...) {};
}
return {result, validArgument };
}
// Some test code
int main() {
std::string valueAsString{};
std::getline(std::cin,valueAsString);
if (const auto& [result, validArgument] = stoiSpecial(valueAsString); validArgument)
std::cout << result << '\n';
else
std::cerr << "\n\n*** Error: Invalid Argument\n\n";
}
Run Code Online (Sandbox Code Playgroud)