Exception handling with stoi function - c++

I have a little problem with exception handling in c++. I need to convert a number to string and if this string contains letters or more than 10 characters I need to give error. Here is the exception-handling part;
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 << "\n\nPlease enter a number (end-of-file to terminate): ";
}
I used stoi function to converting the string to int but I think I need open 2 classes. I don't know why and how becase stoi fucntion own what function already.

I personally find that a regex is no overkill for this. Checking user input with a regex will have no negative impact on performance whatsoever.
But I think that you are more interested in exception handling. You need to read many many pages of a good C++ book to understand exception handling and its use cases.
And maybe, but I do not know, you want simply to catch the standard exceptions thrown by std::stoi. These are:
std::invalid_argument
std::out_of_range
That would be easy with writing
// 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";
}
But maybe you want to learn, how to write own exceptions. For your specific requirements. But please note that your specification, e.g. "more than 10 digits" and "no letter" are maybe not quite what you want. With a machine, where int is 32bit bit, the maximum number that can be converted is: 2147483647. Any number bigger and still having only 10 characters, will throw a std::out_of_range. On the other hand numbers like 123X would be converted by std::stoi to 123. So, maybe your requirements are not so clear.
Anyway, to show you, how you could use own exceptions, I create 2 customized exceptions classes. And to make life easy, I derived those from std::exception (recommended).
See the below example:
#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;
}
Of course you can handle the std::stoi's exception also in your custom converter function. Then only your owwn exceptions are visible.
Please see:
#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;
}
But maybe, what you really want to have, is a function, that encapsulates std::stoi and has an additional return value to show, if it worked or not.
Please note: The last solution will also convert "123X" to 123. That is the difference to the previous versions.
#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 converted\n";
}
return 0;
}

Why not use Regex ? You just create a regex that check if there is letters or more than 10 chars, depending on the return you process the conversion or throw an custom exception.
This may be the regex you are looking for: ^[0-9]{1,10}$
std::regex reg("^[0-9]{1,10}$");
if (std::regex_match(string, reg))
// Do what you want (process convert)
Here is the regex cpp reference : here
Edit: As commented, regex is overkill for this, so you could simply make some basic checks inside you castInput function and throw NonNumber if you find a character in the string, or throw Overflow if string.len > 10.

Related

Converting std::string to uint32_t

I have a string like below:
std::string strl="ffffffffffffffffffffffffffffffffffffffffffff";
I want to convert it into uint32_t variable like below:
uint32_t val = std::stoul(strl, nullptr, 16);
The above operation gives a "SIGABRT" signal and gives error:
terminate called after throwing an instance of 'std::out_of_range'
what(): stoul.
What changes to be done for resolving the issue or it is not possible with uint32_t datatype to store the string.
uint32_t can only store up to 0xffffffff as it's a 32 bit unsigned type, so it's not possible to store your string with that data type.
For the string you present, you'll need a big integer library to parse it.
Boost has a good one, and even includes typedefs like uint1024_t, so it's very simple to use.
See http://www.boost.org/doc/libs/1_58_0/libs/multiprecision/doc/html/index.html
If you really want to store the number in a uint32_t, you'll need to validate it.
I would approach it something like this:
#include <string>
#include <cstdint>
#include <stdexcept>
#include <iostream>
auto parse_hex_uint32(std::string const& input) -> std::uint32_t
try
{
std::size_t read_len = 0;
auto initial_result = std::stoull(input, &read_len, 16);
if (read_len != input.size())
{
throw std::runtime_error("invalid input: " + input);
}
if (initial_result > std::numeric_limits<std::uint32_t>::max())
{
throw std::out_of_range("number too large: " + std::to_string(initial_result));
}
return std::uint32_t(initial_result);
}
catch(...)
{
std::throw_with_nested(std::runtime_error("failed to parse " + input + " as hex uint32"));
}
void print_exception(const std::exception& e, int level = 0)
{
std::cerr << std::string(level, ' ') << "exception: " << e.what() << '\n';
try {
std::rethrow_if_nested(e);
} catch(const std::exception& e) {
print_exception(e, level+1);
} catch(...) {}
}
int main()
{
using namespace std::literals;
auto input = "ffffffffffffffff"s;
try
{
std::cout << parse_hex_uint32(input) << std::endl;
return 0;
}
catch(std::exception& e)
{
print_exception(e);
return 100;
}
}

boost program_options custom validation

i am trying to understand program_options custom validation in order to transform python code into c++ one.
any way
i read in the example that i have to overload validate function
i m trying to find the original function in boost program_options files but in vain
can any body just tell me where is the original validate function which i ll over load it
it is silly question but i wanna know how it validate on default to get idea about the concept of validation and how it is done
thanks in advance
Expanding on my one-line comment, I have always found boost::program_options to be a little deficient in argument validation.
As a result I have found that it's often easier to write a custom class for each option type. Normally program_options uses operator>> to decode the option value, so if you override this you get a chance to throw an exception that program_options recognises. If you use nested exceptions, you can print quite detailed error diagnostics.
Example:
#include <boost/program_options.hpp>
#include <iostream>
#include <iomanip>
#include <sstream>
namespace po = boost::program_options;
// a custom option type
struct foo_or_bar {
std::string value;
// self-describing
static constexpr const char *option_name() { return "foo"; }
static constexpr const char *description() { return "single option only. value must be either foo or bar"; }
// check the value and throw a nested exception chain if it's wrong
void check_value() const
try {
if (value != "foo" and value != "bar") {
std::ostringstream ss;
ss << "value must be foo or bar, you supplied " << std::quoted(value);
throw std::invalid_argument(ss.str());
}
}
catch (...) {
std::throw_with_nested(po::validation_error(po::validation_error::invalid_option_value, option_name()));
}
// overload operators
friend std::istream &operator>>(std::istream &is, foo_or_bar &arg) {
is >> arg.value;
arg.check_value();
return is;
}
friend std::ostream &operator<<(std::ostream &os, foo_or_bar const &arg) {
return os << arg.value;
}
};
// test
void test(int argc, const char **argv) {
foo_or_bar my_foo;
po::options_description desc("test options");
desc.add_options()
(foo_or_bar::option_name(), po::value(&my_foo), foo_or_bar::description());
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
std::cout << "foo is " << my_foo << std::endl;
}
void print_exception(const std::exception& e, int level = 0)
{
std::cerr << std::string(level, ' ') << "exception: " << e.what() << '\n';
try {
std::rethrow_if_nested(e);
} catch(const std::exception& e) {
print_exception(e, level+1);
} catch(...) {}
}
int main() {
{
std::vector<const char *> test_args = {
"executable_name",
"--foo=bar"
};
test(test_args.size(), test_args.data());
}
try {
std::vector<const char *> test_args = {
"executable_name",
"--foo=bob"
};
test(test_args.size(), test_args.data());
}
catch (std::exception const &e) {
print_exception(e);
}
}
expected output:
foo is bar
exception: the argument for option '--foo' is invalid
exception: value must be foo or bar, you supplied "bob"

How to catch char * exceptions in C++

I am trying to catch a char * type exception in main() but the program crashes with the following message: terminate called after throwing an instance of 'char const*'
Here is the code:
#include <iostream>
int main ()
{
char myarray[10];
try
{
for (int n=0; n<=10; n++)
{
if (n>9)
throw "Out of range";
myarray[n]='a';
}
}
catch (char * str)
{
std::cout << "Exception: " << str << std::endl;
}
return 0;
}
Use const:
catch (const char * str)
{
std::cout << "Exception: " << str << std::endl;
}
You don't want to catch char*.
I don't know where this idea comes from that string literals are char*: they're not.
String literals are const char[N] which decays to const char*.
Catch const char*.
Your program is being terminated because, at present, you're actually not handling your exception!
Prefer an exception:
try {
for (int n=0; n<=10; n++) {
if (n>9) throw std::runtime_error("Out of range");
myarray[n]='a';
}
} catch (std::exception const& e) {
std::cout << "Exception: " << e.what() << std::endl;
}
The C++ Standard library provides a base class specifically designed to declare objects to be thrown as exceptions. It is called std::exception and is defined in the header. This class has a virtual member function called what that returns a null-terminated character sequence (of type char *) and that can be overwritten in derived classes to contain some sort of description of the exception.
// using standard exceptions
#include <iostream>
#include <exception>
using namespace std;
class myexception: public exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
} myex;
int main () {
try
{
throw myex;
}
catch (exception& e)
{
cout << e.what() << '\n';
}
return 0;
}
For more help: http://www.cplusplus.com/doc/tutorial/exceptions/
You cannot throw a string like that, you need to create an object.
Replace throw "Out of range" by throw std::out_of_range("Out of range")
Regards,

How to quickly concatenate char arrays?

I'm implementing errors in my class. I mean I'm creating error messages for various misuses that might happen. I know how to combine strings and numbers though std::string or stringstream but I'm wondering if there is a shorter way to do it, heres an example from within the bracket operator:
std::stringstream err;
err << "The key " << key << " is not set.";
throw std::invalid_argument(err.str());
And I'm looking for something that would fit on one line sorta like this:
throw std::invalid_argument("The key " + key + " is not set."); <- obviously broken
Any format that the std::invalid_argument will take is fine.
Simply use std::to_string C++11
throw std::invalid_argument("The key " +
std::to_string( key ) +
" is not set.");
An alternative solution is to create your own exception class with a constructor that takes a uint64_t and creates the error message by itself:
#include <sstream>
#include <stdexcept>
#include <exception>
#include <string>
#include <iostream>
class MyException : public std::invalid_argument
{
private:
static std::string GetMessage(uint64_t key)
{
std::ostringstream err;
err << "The key " << key << " is not set.";
return err.str();
}
public:
MyException(uint64_t key) :
std::invalid_argument(GetMessage(key).c_str()) {}
virtual ~MyException() throw() {}
};
int main()
{
try
{
throw MyException(123);
}
catch (std::exception const &exc)
{
std::cout << exc.what() << "\n";
}
}

Interprete the print out of a denormalized double in C++

What does it mean when a C++ program prints the following number out, and what is the meaning of the H in the end?
-6.38442e-86H
The entire system is too large to add here, however here is the code that printed out the particular double.
try{
newLogLikelihoodEM= hmm->learningLogLikelihood(data, Arglist::getDiffLogLikelihood(), fileNumbers, rng);
}
catch (SingularCovarianceMatrixException &scme)
{
std::cout << scme.what() << ": doing learning, so restarts for this start-point" << std::endl;
noRestarts++;
restart = true;
}
and the exception class
class SingularCovarianceMatrixException: public std::exception
{
double det;
public:
SingularCovarianceMatrixException(double det):det(det){};
virtual const char* what() const throw()
{
std::stringstream msg;
msg<< "Singular covariance matrix: determinant="<<det;
return msg.str().c_str();
}
};
And the exception is thrown by
if(*detCovarianceMatrix<1e-300)
{
throw SingularCovarianceMatrixException(*detCovarianceMatrix);
}
H is not part of the number. This is not a valid suffix for a floating point number. Something else in your code should be printing it.
H is not a valid floating point suffix, I can not find a good reference to prove this but we can show that it is not a valid conversion using this code:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToDouble(std::string const& s,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
double x;
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion("convertToDouble(\"" + s + "\")");
return x;
}
int main()
{
double d1 = convertToDouble("-6.38442e-86") ;
std::cout << d1 << std::endl ;
d1 = convertToDouble("-6.38442e-86H");
std::cout << d1 << std::endl ;
}
Which is code I took from one of my previous answers on how to check if a string is an integer.