C++ convert string to hexadecimal and vice versa
What is the best way to convert a string to hex and vice versa in C++?
Example:
- A string like
"Hello World"
to hex format:48656C6C6F20576F726C64
- And from hex
48656C6C6F20576F726C64
to string:"Hello World"
Solution 1:
A string like "Hello World" to hex format: 48656C6C6F20576F726C64.
Ah, here you go:
#include <string>
std::string string_to_hex(const std::string& input)
{
static const char hex_digits[] = "0123456789ABCDEF";
std::string output;
output.reserve(input.length() * 2);
for (unsigned char c : input)
{
output.push_back(hex_digits[c >> 4]);
output.push_back(hex_digits[c & 15]);
}
return output;
}
#include <stdexcept>
int hex_value(unsigned char hex_digit)
{
static const signed char hex_values[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
int value = hex_values[hex_digit];
if (value == -1) throw std::invalid_argument("invalid hex digit");
return value;
}
std::string hex_to_string(const std::string& input)
{
const auto len = input.length();
if (len & 1) throw std::invalid_argument("odd length");
std::string output;
output.reserve(len / 2);
for (auto it = input.begin(); it != input.end(); )
{
int hi = hex_value(*it++);
int lo = hex_value(*it++);
output.push_back(hi << 4 | lo);
}
return output;
}
(This assumes that a char has 8 bits, so it's not very portable, but you can take it from here.)
Solution 2:
string ToHex(const string& s, bool upper_case /* = true */)
{
ostringstream ret;
for (string::size_type i = 0; i < s.length(); ++i)
ret << std::hex << std::setfill('0') << std::setw(2) << (upper_case ? std::uppercase : std::nouppercase) << (int)s[i];
return ret.str();
}
int FromHex(const string &s) { return strtoul(s.c_str(), NULL, 16); }
Solution 3:
Using lookup tables and the like works, but is just overkill, here are some very simple ways of taking a string to hex and hex back to a string:
#include <stdexcept>
#include <sstream>
#include <iomanip>
#include <string>
#include <cstdint>
std::string string_to_hex(const std::string& in) {
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (size_t i = 0; in.length() > i; ++i) {
ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(in[i]));
}
return ss.str();
}
std::string hex_to_string(const std::string& in) {
std::string output;
if ((in.length() % 2) != 0) {
throw std::runtime_error("String is not valid length ...");
}
size_t cnt = in.length() / 2;
for (size_t i = 0; cnt > i; ++i) {
uint32_t s = 0;
std::stringstream ss;
ss << std::hex << in.substr(i * 2, 2);
ss >> s;
output.push_back(static_cast<unsigned char>(s));
}
return output;
}