如何将十六进制值的字符串转换为字符串?

Nul*_*ion 14 c++ string ascii stl

说我有一个像这样的字符串:

string hex = "48656c6c6f";
Run Code Online (Sandbox Code Playgroud)

其中每两个字符对应于其ASCII值的十六进制表示,例如:

0x48 0x65 0x6c 0x6c 0x6f = "Hello"
Run Code Online (Sandbox Code Playgroud)

那么如何"hello""48656c6c6f"不必创建查找ASCII表的情况下获得?atoi()显然不会在这里工作.

zwo*_*wol 18

十六进制数字很容易转换为二进制:

// C++98 guarantees that '0', '1', ... '9' are consecutive.
// It only guarantees that 'a' ... 'f' and 'A' ... 'F' are
// in increasing order, but the only two alternative encodings
// of the basic source character set that are still used by
// anyone today (ASCII and EBCDIC) make them consecutive.
unsigned char hexval(unsigned char c)
{
    if ('0' <= c && c <= '9')
        return c - '0';
    else if ('a' <= c && c <= 'f')
        return c - 'a' + 10;
    else if ('A' <= c && c <= 'F')
        return c - 'A' + 10;
    else abort();
}
Run Code Online (Sandbox Code Playgroud)

所以要做整个字符串看起来像这样:

void hex2ascii(const string& in, string& out)
{
    out.clear();
    out.reserve(in.length() / 2);
    for (string::const_iterator p = in.begin(); p != in.end(); p++)
    {
       unsigned char c = hexval(*p);
       p++;
       if (p == in.end()) break; // incomplete last digit - should report error
       c = (c << 4) + hexval(*p); // + takes precedence over <<
       out.push_back(c);
    }
}
Run Code Online (Sandbox Code Playgroud)

你可能会问,为什么人会做这种方式时,有strtol,而且使用它是显著较少的代码(如詹姆斯·柯伦的答案).那么,这种做法是规模的全小数顺序慢,因为它会将每两个字节的块(可能分配堆内存的话),然后调用不能作为有效写成一般的文本到数字的转换例程以上专业代码.(使用istringstream)基督教的做法是慢五倍.这里有一个情节标杆-你能分辨出来,即使数据进行解码的一小块,并作为差异变大变得明目张胆.(请注意,两个轴都是对数刻度.)

基准比较图

这是不成熟的优化吗?一定不行.这种操作被推入库例程中,被遗忘,然后每秒调用数千次.它需要尖叫.几年前我参与了一个项目,在内部大量使用SHA1校验和 - 我们通过将它们存储为原始字节而不是十六进制来获得10-20%的常用操作加速,仅当我们必须将它们显示到用户 - 那就是已经调整为死亡的转换功能.在这里,人们可能真的更喜欢简洁性和性能,这取决于更大的任务是什么,但如果是这样,为什么你用C++编写代码呢?

此外,从教学的角度来看,我认为展示这类问题的手工编码示例是有用的; 它揭示了计算机必须做的更多事情.


Jam*_*ran 17

int len = hex.length();
std::string newString;
for(int i=0; i< len; i+=2)
{
    string byte = hex.substr(i,2);
    char chr = (char) (int)strtol(byte.c_str(), null, 16);
    newString.push_back(chr);
}
Run Code Online (Sandbox Code Playgroud)

  • 我同意sbi:使用size_t.无论如何,您的IDE /编译器应将此标记为警告. (2认同)

小智 6

我无法评论,但zwol的解决方案有一个错误:

c = c << 4 + hexval(*p);
Run Code Online (Sandbox Code Playgroud)

是正确的

c = (c << 4) + hexval(*p);
Run Code Online (Sandbox Code Playgroud)

因为移位运算符的优先级低于add


Chr*_*mer 5

std::string str("48656c6c6f");
std::string res;
res.reserve(str.size() / 2);
for (int i = 0; i < str.size(); i += 2)
{
    std::istringstream iss(str.substr(i, 2));
    int temp;
    iss >> std::hex >> temp;
    res += static_cast<char>(temp);
}
std::cout << res;
Run Code Online (Sandbox Code Playgroud)