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;
}
}
Related
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.
boost::lexical_cast throwing exception during converting string to int8_t, but int32_t - norm.
What can be wrong with int8_t ?
#include <iostream>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
int main()
{
try
{
const auto a = boost::lexical_cast<int8_t>("22");
std::cout << a << std::endl;
}
catch( std::exception &e )
{
std::cout << "e=" << e.what() << std::endl;
}
}
For boost::lexical_cast, the character type of the underlying stream is assumed to be char unless either the Source or the Target requires wide-character streaming, in which case the underlying stream uses wchar_t. Following types also can use char16_t or char32_t for wide-character streaming
Boost Lexical Cast
So after doing below changes in your code:
#include <iostream>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
int main()
{
try
{
const auto a = boost::lexical_cast<int8_t>("2");
const auto b = boost::lexical_cast<int16_t>("22");
std::cout << a << " and "<< b << std::endl;
}
catch( std::exception &e )
{
std::cout << "e=" << e.what() << std::endl;
}
return 0;
}
Gives below output
2 and 22
So, I feel that each character is taken as char.
So, for const auto a = boost::lexical_cast<int16_t>("2"); 2 is taken as single char which require int8_t.
And, for const auto b = boost::lexical_cast<int16_t>("22"); 22 is taken as two char values which require int16_t.
I hope it helps!
What I want to know is, If I ask a user to input something, how will I output if the input is a Integer or String or a Float Value. I want some method to check the data type of the input in C++14.
For eg.
If the input is "Hello world"
Output should be : "The input is String"
If the input is "134"
Output should be : "The input is integer"
If the input is "133.23"
Output should be : "The input is float"
Read string.
In <string>, the standard library provides a set of functions for extracting numeric values from their character representation in a string or wstring.
Use x=stoi(s,p). Check p - if whole string was read - it is integer.
Do the same with x=stof(s,p) or x=stod(s,p), x=stold(s,p) to check for float/double/long double.
If everything fails - it is string.
The user will always input a string, what you can do is try to convert it to a float, if it succeeds then it probably is a float or an int.
If the float conversion doesnt succeed then its probably not a number.
#include <iostream>
#include <string>
#include <boost/variant.hpp>
#include <sstream>
using myvariant = boost::variant<int, float, std::string>;
struct emit : boost::static_visitor<void>
{
void operator()(int i) const {
std::cout << "It's an int: " << i << '\n';
}
void operator()(float f) const {
std::cout << "It's a float: " << f << '\n';
}
void operator()(std::string const& s) const {
std::cout << "It's a string: " << s << '\n';
}
};
auto parse(const std::string& s) -> myvariant
{
char* p = nullptr;
auto i = std::strtol(s.data(), &p, 10);
if (p == s.data() + s.size())
return int(i);
auto f = std::strtof(s.data(), &p);
if (p == s.data() + s.size())
return f;
return s;
}
void test(const std::string& s)
{
auto val = parse(s);
boost::apply_visitor(emit(), val);
}
int main()
{
test("Hello world");
test("134");
test("133.23");
}
expected output:
It's a string: Hello world
It's an int: 134
It's a float: 133.23
The input is in a string. Without additional agreements, how could you possibly know if the user intended "1" to be the string containing the character '1' or a string representation of the integer 1?
If you decide that "if it can be interpreted as an int, then it's an int. If it can be a double, then it's a double. Else it's a string", then you can just do a series of conversions until one works, or do some format checking, perhaps with a regexp.
Since all ints can be converted into doubles, and string representations of doubles can be converted into ints (perhaps with some junk left over) if you care about the difference, you probably need to check for indicators of it being a double (digits with perhaps a . in it, possibly a 'e' with +/- possibly after it. Etc. You can find regexps on the internet, depending on what you want to allow, leading +, e-notation, etc.
If it's an int, you can use regex ^\d+$, else if it's a double, [+-]?(?:0|[1-9]\d*)(?:.\d*)?(?:[eE][+-]?\d+)? else it's a string.
Here's some code that seems to work. :)
#include <iostream>
#include <string>
#include <regex>
using namespace std;
void handleDouble(double d) {
std::cout << "Double = " << d << "\n";
}
void handleInt(int i) {
std::cout << "Int = " << i << "\n";
}
void handleString(std::string const & s) {
std::cout << "String = " << s << "\n";
}
void parse(std::string const& input) {
static const std::regex doubleRegex{ R"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)" };
static const std::regex intRegex{ R"(\d+)"};
if (std::regex_match(input, intRegex)){
istringstream inputStream(input);
int i;
inputStream >> i;
handleInt(i);
}
else if (std::regex_match(input, doubleRegex)) {
istringstream inputStream(input);
double d;
inputStream >> d;
handleDouble(d);
}
else {
handleString(input);
}
}
int main()
{
parse("+4.234e10");
parse("1");
parse("1.0");
parse("123abc");
}
output:
Double = 4.234e+10
Int = 1
Double = 1
String = 123abc
You can easily wrap string.strof for float or string.stroi for int in try-catch block:
#include <string>
bool isFloat(string str) {
try {
float floatCheck = stof(str);
return true;
}
catch (...) {
return false;
}
}
bool isInt(string str) {
try {
int intCheck = stoi(str);
return true;
}
catch (...) {
return false;
}
}
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";
}
}
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.