Let's say you've got a std::string("DEADBEEF")
, what would be the most elegant way to store each two values in a std::vector (most likely a std::vector<unsigned char>
, if possible) so the std::vector
would look a little like { 0xDE, 0xAD, 0xBE, 0xEF }
(if it was an array)? And what would be the nicest way to undo that (std::vector<unsigned char>
-> std::string
).
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
how about (no fancy stl juggling though):
#include <string>
#include <vector>
// exception thrown by the encoder
class DecodeError {
public:
DecodeError() {}
DecodeError(const char* s): msg(s) {}
DecodeError(const std::string& s): msg(s) {}
const char* what() { return msg.c_str(); }
private:
std::string msg;
};
class HexEncoder {
public:
void decode(const std::string& str, std::vector<unsigned char>& v);
private:
unsigned char decode(char);
};
void HexEncoder::decode(const std::string& s, std::vector<unsigned char>& v)
{
if (s.size() % 2 != 0)
throw DecodeError("invalid string length");
v.reserve(s.size() / 2);
std::string::const_iterator it=s.begin();
while (it != s.end()) {
unsigned char nibble1 = decode(*it++);
unsigned char nibble2 = decode(*it++);
v.push_back(nibble1 << 4 + nibble2);
}
}
unsigned char HexEncoder::decode(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
throw DecodeError("invalid character");
}
int main()
{
std::string s("DEADBEEF");
std::vector<unsigned char> v;
HexEncoder enc;
enc.decode(s, v);
}
回答2:
for(std::iterator<string> it = str.begin(); it != str.end(); std::advance(it, 2))
{
char tmp;
std::copy(it, it + 2, tmp);
scanf("%02X", &tmp);
vect.push_back(tmp);
}
This is a rough draft of your conversion, but I'm not sure that it works correctly.
回答3:
I'd go for simple plain loops
int hexValue(int c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
return -1;
}
std::vector<unsigned char> toBin(const std::string& s)
{
std::vector<unsigned char> result;
for (int i=0,n=s.size(); i<n-1; i+=2)
{
int x1 = hexValue(s[i]);
int x2 = hexValue(s[i+1]);
if (x1 >= 0 && x2 >= 0)
result.push_back(x1*16 + x2);
}
return result;
}
std::string toHex(const std::vector<unsigned char>buf)
{
const char *hex = "0123456789ABCDEF";
int n = buf.size();
std::string result(n*2, ' ');
for (int i=0; i<n; i++)
{
result[i*2] = hex[buf[i]>>4];
result[i*2+1] = hex[buf[i]&15];
}
return result;
}
If you need this conversion to be very fast (assuming the input is big enough and formally correct) ...
std::vector<unsigned char> toBin(const std::string& s)
{
static unsigned char H[256], L[256];
if (L['1'] == 0)
{
for (int i=0; i<10; i++)
{
H['0'+i] = (i<<4);
L['0'+i] = i;
}
for (int i=0; i<6; i++)
{
H['a'+i] = H['A'+i] = ((10+i)<<4);
L['a'+i] = L['A'+i] = (10+i);
}
}
std::vector<unsigned char> result(s.size()>>1);
for (int i=0,n=s.size(); i<n-1; i+=2)
result[i>>1] = H[s[i]]+L[s[i+1]];
return result;
}
回答4:
As my project already depends on boost, I'd use boost/algorithm/hex.hpp:
#include <string>
#include <vector>
#include <iterator>
#include <boost/algorithm/hex.hpp>
...
string stringValue("DEADBEEF");
vector<unsigned char> vectorValue;
String to hex conversion:
boost::algorithm::unhex(stringValue, back_inserter(vectorValue));
For hex to string conversion:
boost::algorithm::hex(vectorValue, back_inserter(stringValue));