使用 stoi 功能进行异常处理
Exception handling with stoi function
我在 c++ 中处理异常时遇到了一点问题。我需要将数字转换为字符串,如果此字符串包含字母或超过 10 个字符,我需要给出错误。这是异常处理部分;
while ( cin >> input )
{
try
{
convert = castInput( input );
cout << "The number entered was: " << convert;
}
catch ( NonNumber &excp )
{
cout << "INVALID INPUT: " << excp.what();
}
catch ( Overflow &excp )
{
cout << "INVALID INPUT: " << excp.what();
}
cout << "nnPlease enter a number (end-of-file to terminate): ";
}
我使用 stoi 函数将字符串转换为 int,但我认为我需要打开 2 个类。我不知道为什么以及如何拥有什么功能。
我个人认为正则表达式并不过分。使用正则表达式检查用户输入不会对性能产生任何负面影响。
但我认为您对异常处理更感兴趣。您需要阅读一本好的C++书的许多页才能理解异常处理及其用例。
也许,但我不知道,你只是想捕捉std::stoi抛出的标准异常。这些是:
- 标准::invalid_argument
- 标准::out_of_range
那很容易写
// Standard exceptions for stoi
catch (const std::invalid_argument & e) {
std::cout << e.what() << "n";
}
catch (const std::out_of_range & e) {
std::cout << e.what() << "n";
}
但也许你想学习如何编写自己的异常。满足您的特定要求。但请注意,您的规格,例如"超过 10 位数字"和"无字母"可能不是您想要的。对于 int 为 32 位位的机器,可以转换的最大数字为:2147483647。任何更大的数字仍然只有 10 个字符,都会抛出一个std::out_of_range
。另一方面,像 123X 这样的数字将被std::stoi
转换为 123。所以,也许你的要求不是那么清楚。
无论如何,为了向您展示如何使用自己的异常,我创建了 2 个自定义异常类。为了让生活变得轻松,我从std::exception(推荐(中衍生出这些。
请参阅以下示例:
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>
class StoiException : public std::exception
{
public:
StoiException(const std::string& msg) : message(msg) {}
virtual const char* what() const noexcept override { return message.c_str(); }
protected:
void setMessage(const std::string& msg) { message = msg; }
protected:
std::string message{};
};
class NoNumber : StoiException
{
public:
NoNumber(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> NoNumber: ") + msg); }
virtual const char* what() const noexcept override { return message.c_str(); }
};
class Overflow : StoiException
{
public:
Overflow(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> Overflow: ") + msg); }
virtual const char* what() const noexcept override { return message.c_str(); }
};
int castInput(std::string& input) {
int result{};
// Check, if there is any letter in the input string
if (std::any_of(input.begin(), input.end(), isalpha)) {
// If so, than throw
throw NoNumber(input);
}
// Check, if string has more than 10 characters
if (input.length() > 10) {
// If so, than throw
throw Overflow(input);
}
result = std::stoi(input);
return result;
}
std::istringstream testCin{ R"(123
567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };
int main() {
std::string input{};
// Read all input
while (testCin >> input) {
try {
// Convert
int convert = castInput(input);
// This will only be shown , if there is no exception
std::cout << "nConverted Number is: " << convert << "n";
}
// Catch all exceptions
catch (const NoNumber & e) {
std::cout << e.what() << "n";
}
catch (const Overflow & e) {
std::cout << e.what() << "n";
}
// Standard exceptions for stoi
catch (const std::invalid_argument & e) {
std::cout << e.what() << "n";
}
catch (const std::out_of_range & e) {
std::cout << e.what() << "n";
}
}
return 0;
}
当然,您也可以在自定义转换器函数中处理std::stoi
的异常。然后,只有您的 owwn 异常可见。
请看:
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>
class StoiException : public std::exception
{
public:
StoiException(const std::string& msg) : message(msg) {}
virtual const char* what() const noexcept override { return message.c_str(); }
protected:
void setMessage(const std::string& msg) { message = msg; }
protected:
std::string message{};
};
class NoNumber : StoiException
{
public:
NoNumber(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> NoNumber: ") + msg); }
virtual const char* what() const noexcept override { return message.c_str(); }
};
class Overflow : StoiException
{
public:
Overflow(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> Overflow: ") + msg); }
virtual const char* what() const noexcept override { return message.c_str(); }
};
int castInput(std::string& input) {
int result{};
// Check, if there is any letter in the input string
if (std::any_of(input.begin(), input.end(), isalpha)) {
// If so, than throw
throw NoNumber(input);
}
// Check, if string has more than 10 characters
if (input.length() > 10) {
// If so, than throw
throw Overflow(input);
}
try {
result = std::stoi(input);
}
// Standard exceptions for stoi
catch (const std::invalid_argument & e) {
throw NoNumber(input);
}
catch (const std::out_of_range & e) {
throw Overflow(input);
}
return result;
}
std::istringstream testCin{ R"(123
567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };
int main() {
std::string input{};
// Read all input
while (testCin >> input) {
try {
// Convert
int convert = castInput(input);
// This will only be shown , if there is no exception
std::cout << "nConverted Number is: " << convert << "n";
}
// Catch all exceptions
catch (const NoNumber & e) {
std::cout << e.what() << "n";
}
catch (const Overflow & e) {
std::cout << e.what() << "n";
}
}
return 0;
}
但也许,你真正想要的是一个函数,它封装std::stoi
并有一个额外的返回值来显示它是否有效。
请注意:最后一个解决方案也会将"123X"转换为 123。这是与以前版本的区别。
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>
std::pair<bool, int> castInput(std::string& input) {
bool ok{ false };
int result{};
try {
result = std::stoi(input);
ok = true;
}
// Catch stoi errors
catch (const std::invalid_argument & e) {}
catch (const std::out_of_range & e) {}
return {ok, result};
}
std::istringstream testCin{ R"(123
567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };
int main() {
std::string input{};
// Read all input
while (testCin >> input) {
const auto [ok, convert] = castInput(input);
if (ok)
std::cout << "Converted value: " << convert << "n";
else
std::cout << "String '" << input << "' could not be convertedn";
}
return 0;
}
为什么不使用正则表达式?您只需创建一个正则表达式,检查是否有字母或超过 10 个字符,具体取决于您处理转换或抛出自定义异常的返回。
这可能是您正在寻找的正则表达式:^[0-9]{1,10}$
std::regex reg("^[0-9]{1,10}$");
if (std::regex_match(string, reg))
// Do what you want (process convert)
这是正则表达式 cpp 参考:这里
编辑:如前所述,正则表达式对此矫枉过正,因此您可以简单地在函数内部进行一些基本检查castInput
并在字符串中找到字符时抛出NonNumber
,或者如果 string.len> 10Overflow
则抛出。
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Firebase C++VS2018 SDL2-在Firebase::app::create(..)上执行异常处理
- 使用 stoi 功能进行异常处理
- 子系统中的异常处理:本机
- 与异常处理程序中的操作员<<不匹配
- 数组 C++ 上的异常处理程序
- 异常处理:如果用户输入不是三个特定字符之一
- C++ 异常处理错误输出
- 视觉 std::矢量无异常:警告 C4530:使用了C++异常处理程序,但未启用展开语义.指定 /EHsc
- C++交换机状态异常处理
- 在字符串类上的成员函数和out_of_range异常处理
- 奇怪的消息 (_Base_bitset::_M_do_to_ulong) 从溢出异常处理程序中打印出来
- 执行视觉工作室异常处理模式
- 为什么隐式转换在异常处理中从派生到基?
- C++执行期间的类成员函数错误/异常处理
- C++ 中未处理的异常处理程序
- 用户定义的异常处理
- C :ScopeGuard vs返回支票和异常处理
- 出乎意料的堆损坏在功能中发生在异常处理中