I see in this topic C convert hex string to signed integer that boost::lexical_cast
can convert hexadecimal inside string to another type (int, long...)
but when I tried this code:
std::string s = "0x3e8";
try {
auto i = boost::lexical_cast<int>(s);
std::cout << i << std::endl; // 1000
}
catch (boost::bad_lexical_cast& e) {
// bad input - handle exception
std::cout << "bad" << std::endl;
}
It ends with a bad lexical cast exception !
boost doesn't support this kind of cast from string hex to int ?
CodePudding user response:
As per the answer from C convert hex string to signed integer:
It appears that since
lexical_cast<>
is defined to have stream conversion semantics. Sadly, streams don't understand the "0x" notation. So both theboost::lexical_cast
and my hand rolled one don't deal well with hex strings.
Also, as per boost::lexical_cast<>
documentation
The
lexical_cast
function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text. The simplification it offers is in expression-level convenience for such conversions. For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior oflexical_cast
, the conventionalstd::stringstream
approach is recommended.
So for more involved conversion, std::stringstream
is recommended.
If you have access to C 11 compiler, you can use std::stoi
to convert any hexadecimal sting to an integer value.
stoi
prototype is:
int stoi( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
Your program can be converted to
int main() {
std::string s = "3e8";
auto i = std::stoi(s, nullptr, 16);
std::cout << i << '\n';
}
And the output will be
1000
CodePudding user response:
What you want exists in Boost Convert:
Boost.Convert builds on the boost::lexical_cast experience and takes those type conversion/transformation-related ideas further
- to be applicable to a wider range of conversion-related deployment scenarios,
- to provide a more flexible, configurable and extendible type-conversion framework,
- to provide generic consistent behavior,
- to unify and to uniformly deploy various conversion facilities through one consistent interface.
Simple Usage
You can e.g. use stream conversion:
boost::cnv::cstream converter;
You can configure it with the manipulators you want, e.g.:
converter(std::hex)(std::skipws); // IO manipulators
You could use directly:
boost::optional<int> i;
converter(s, i);
std::cout << i << std::endl; // 1000
But I'd suggest applying with pre-configured error-handling:
auto f = apply<int>(std::ref(converter))
.value_or(-1); // decorate error-handling
Now you can simply write:
for (auto s : cases)
std::cout << f(s) << std::endl;
Live Demo
#include <boost/convert.hpp>
#include <boost/convert/stream.hpp>
#include <iostream>
static const std::string cases[]{
"0x3e8", "3e8", "-7a", "-0x7a",
"0x-7a", // error
};
int main() {
boost::cnv::cstream converter;
converter(std::hex)(std::skipws); // IO manipulators
auto f = apply<int>(std::ref(converter)).value_or(-1); // decorate error-handling
for (auto s : cases)
std::cout << std::quoted(s) << " -> " << f(s) << std::endl;
auto g = apply<int>(std::ref(converter)); // throwing
for (auto s : cases)
try {
std::cout << std::quoted(s) << " -> " << g(s) << std::endl;
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
}
}
Prints
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> -1
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> Attempted to access the value of an uninitialized optional object.