【问题标题】:Better way to convert a vector of uint8 to an ascii hexadecimal string将 uint8 向量转换为 ascii 十六进制字符串的更好方法
【发布时间】:2014-10-22 08:50:29
【问题描述】:

我编写了以下函数来将 uint8_tstd::vector 转换为 ascii 十六进制 string (gnu++98 标准)。

 ...
string uint8_vector_to_hex_string(const vector<uint8_t>& v) {
    stringstream ss;
    vector<uint8_t>::const_iterator it;

    for (it = v.begin(); it != v.end(); it++) {
        char hex_char[2];
        sprintf(hex_char, "%x", *it);
        ss << "\\x" << hex_char;
    }

    return ss.str();
}
 ...

它工作正常。我想知道是否有更好的方法来进行这种转换,也许不能同时使用stringstream 对象和sprintf 函数。有什么建议吗?

【问题讨论】:

  • 使用分析器,找到瓶颈,让它工作得更快。
  • 如何打印大写字母(例如 0x1B 而不是 0x1b)?
  • @Anna Vopureta:使用 %X 而不是 %x。

标签: c++ vector std


【解决方案1】:

您可以直接使用字符串流进行十六进制格式化:

#include <string>
#include <sstream>
#include <iostream>

...

string uint8_vector_to_hex_string(const vector<uint8_t>& v) {
    stringstream ss;
    ss << std::hex << std::setfill('0');
    vector<uint8_t>::const_iterator it;

    for (it = v.begin(); it != v.end(); it++) {
        ss << "\\x" << std::setw(2) << static_cast<unsigned>(*it);
    }

    return ss.str();
}
...

【讨论】:

  • 对于那些想知道的人,你需要有#include &lt;string&gt; #include &lt;sstream&gt; #include &lt;iostream&gt;
【解决方案2】:

(注意:答案适用于标准 C++;可能需要对范围迭代进行少量修改才能在较旧的方言中工作。我认为这些对算法效率的核心问题无关紧要,而该核心问题对问题很重要.)


您可以通过意识到您基本上提前知道答案并且不需要做所有这些动态工作,从而为自己节省大量工作。

std::string uint8_vector_to_hex_string(const vector<uint8_t>& v)
{
    std::string result;
    result.reserve(v.size() * 2);   // two digits per character

    static constexpr char hex[] = "0123456789ABCDEF";

    for (uint8_t c : v)
    {
        result.push_back(hex[c / 16]);
        result.push_back(hex[c % 16]);
    }

    return result;
}

本着“识别算法”的精神,这里有一个用于数字序列的位值格式化的分离算法。首先是用例:

#include <iostream>
#include <string>
#include <vector>

// bring your own alphabet
constexpr char Alphabet[] = "0123456789ABCDEF";

// input
std::vector<unsigned char> const v { 31, 214, 63, 9 };

// output (Note: *our* responsibility to make allocations efficient)
std::string out;
out.reserve(v.size() * 2);

// the algorithm
place_value_format<char,     // output type
                      2,     // fixed output width
                     16>(    // place-value number base
    v.begin(), v.end(),      // input range
    std::back_inserter(out), // output iterator
    Alphabet);               // digit representation

现在算法:

#include <algorithm>
#include <iterator>

template <typename Out, std::size_t NDigits, std::size_t Base,
          typename InItr, typename OutItr>
OutItr place_value_format(InItr first, InItr last, OutItr out, Out const * digits)
{
    for (; first != last; ++first)
    {
        Out unit[NDigits];

        auto val = *first;

        for (auto it = std::rbegin(unit); it != std::rend(unit); ++it)
        {
            *it = digits[val % Base];
            val /= Base;
        }

        out = std::copy(std::begin(unit), std::end(unit), out);
    }

    return out;
}

【讨论】:

    【解决方案3】:

    如果您不介意在您的项目中使用 Boost,您可以使用 boost::hex

    #include <boost/algorithm/hex.hpp>
    
    std::string uint8_vector_to_hex_string(const std::vector<uint8_t> & v) {
        std::string result;
        result.reserve(v.size() * 2);
        boost::algorithm::hex(v.begin(), v.end(), std::back_inserter(result));
        return result;
    }
    

    【讨论】:

      【解决方案4】:

      我会选择不依赖其他类的东西:

      std::string uint8_vector_to_hex_string(const std::vector<uint8_t>& v) {
          std::string result;
          result.resize(v.size() * 2);
          const char letters[] = "0123456789ABCDEF";
          char* current_hex_char = &result[0];
          for (uint8_t b : v) {
              *current_hex_char++ = letters[b >> 4];
              *current_hex_char++ = letters[b & 0xf];
          }
          return result;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-21
        • 2013-09-07
        • 2015-05-22
        • 2019-10-20
        • 2011-10-26
        • 2017-03-11
        • 2014-11-16
        • 2011-06-14
        相关资源
        最近更新 更多