从字符串生成C++字节数组

3

给定一个十六进制字符的字符串, 我想从中创建一个字节数组。例如,给定字符串"1A2B3C",我希望我的数组包含0x1A,0x2B,0x3C。

我已经使用下面的代码使其工作,但是希望看到更有效率的做法。

(此时已经完成了字符串长度等的检查)。

// Go through the string

int k = 0;
stringstream s;
for (int i = 0; i < STRING_SIZE; i++)
{
    // Get 2 digits at a time and store in a temp variable

    s.str("");
    s << key[k++];
    s << key[k++];

    char temp[2];
    memcpy(temp, s.str().c_str(), 2);

    // Get the hex value and store in final array

    actualArray[i] = (unsigned char)strtol(temp, 0, 16);
}

2
如果您拥有可工作的代码并关心效率,您可以查看 https://codereview.stackexchange.com/。 - Alex Johnson
与其使用 stringstreammemcpy 这些复杂而低效的操作,你可以直接使用 const char temp[3] = {key[i], key[i+1]};(并将 i++ 替换为 i += 2)。这里的 3 是为了使字符串以零结尾。如果没有这个,调用 strtol 就会产生未定义行为。 - Cheers and hth. - Alf
3个回答

4
假设key是一个std::string,你的循环体可以这样写:
actualArray[i] = (unsigned char)std::stol(key.substr(i*2, 2), 0, 16);

如果key是一个字符数组,它将是这样的:
actualArray[i] = (unsigned char)std::stol(std::string(key + i*2, 2), 0, 16);

太棒了。我需要进行微小的调整,因为strtol不接受字符串。但是这段代码完美地运行了。谢谢 :) - user1408542
@user1408542 抱歉,应该是 std::stol - Alan Birtles

3
您可以使用类似这样的东西。
#include <string>
#include <vector>
#include <cstdint>
#include <cassert>

std::uint8_t char_to_nibble(char c)
{
    assert((c>='0' && c<='9') || (c>='A' && c<='F'));
    if ((c >= '0') && (c <= '9'))
        return c-'0';
    else
        return c-'A' + 0xA;
}

void str2ba(const std::string &src, std::vector<std::uint8_t> &dst)
{
    assert(src.size() % 2 == 0);
    dst.reserve(src.size()/2);
    dst.clear();
    auto it = src.begin();
    while(it != src.end()) {
        std::uint8_t hi = char_to_nibble(*it++);
        std::uint8_t lo = char_to_nibble(*it++);
        dst.push_back(hi*16+lo);
    }
}

除非您保证在调用char_to_nibble()之前输入始终为大写字母,否则应考虑处理'a'..'f',而不仅仅是'A'..'F' - Remy Lebeau

3

您不需要通过stringstream来获取十六进制值。直接将char映射到int,并使用位移运算获取十六进制字符表示的十进制值。

unsigned int getInt(char c)
{
   if ( isdigit(c) )
   {
      return c-'0';
   }

   if ( c >= 'a' && c <= 'f' )
   {
      return (c - 'a' + 10);
   }

   if ( c >= 'A' && c <= 'F' )
   {
      return (c - 'A' + 10);
   }

   assert(false);

   // Keep the compiler happy.
   return 0;
}

并将其用作:
for (int i = 0; i < STRING_SIZE; i += 2)
{
    int hex = getInt(key[i]) << 4 + getInt(key[i+1]);
    // Add hex to the array where you wish to store it.
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接