十六进制字符串到uint8_t msg []

时间:2019-04-01 12:52:18

标签: c++ arrays hex uint8t

我要转换十六进制字符串中的字符

"0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98" 

uint8_t msg[],却不知道该怎么做。

看似简单,但一直无法弄清。我想将每个字符转换为uint8_t十六进制值。例如,如果我有

string result = "0123456789abcdef";

如何将字符串转换为:

uint8_t msg[] = "0123456789abcdef";

2 个答案:

答案 0 :(得分:0)

此功能(感谢Converting a hex string to a byte array

Environment.SetEnvironmentVariable("OPENCV_FFMPEG_CAPTURE_OPTIONS", "protocol_whitelist;file,rtp,udp", EnvironmentVariableTarget.User);

使用上述函数,我们获得字节向量,并调用方法data()

我想感谢社区,现在一切正常。感谢您的评论,我已经迫切希望做不到这么简单的事情。 特别感谢@ johnny-mopp

答案 1 :(得分:0)

编辑-已更新为就绪字节而不是字符

您无需使用.substr()并调用C strtol并强制转换为uint8_t,而只需将istringstreamstd::setbase(16)一起使用以读取字节即可。将unsigned的值直接放入您的vector<uint8_t> msg。参见std::setbase

例如,您可以从包含十六进制字符的字符串中创建一个istringstream,然后将其与uint8_t的向量和一个临时unsigned一起直接读入,然后推回您可以做的向量,例如

    std::string result ("0123456789abcdef");    /* input hex string */
    std::string s2;                             /* string for 2-chars */
    std::istringstream ss (result);             /* stringstream of result */
    std::vector<uint8_t> msg;                   /* vector of uint8_t */

    while ((ss >> std::setw(2) >> s2)) {    /* read 2-char at a time */
        unsigned u;                         /* tmp unsigned value */
        std::istringstream ss2 (s2);        /* create 2-char stringstream */
        ss2 >> std::setbase(16) >> u;       /* convert hex to unsigned */
        msg.push_back((uint8_t)u);          /* add value as uint8_t */
    }

通过这种方式,使用result读取的std::setw(2)中的每个2个字符用于创建2个字符的字符串流,然后使用unsigned将其转换为std::setbase(16)值。一个完整的例子是:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>

int main (void) {

    std::string result ("0123456789abcdef");    /* input hex string */
    std::string s2;                             /* string for 2-chars */
    std::istringstream ss (result);             /* stringstream of result */
    std::vector<uint8_t> msg;                   /* vector of uint8_t */

    while ((ss >> std::setw(2) >> s2)) {    /* read 2-char at a time */
        unsigned u;                         /* tmp unsigned value */
        std::istringstream ss2 (s2);        /* create 2-char stringstream */
        ss2 >> std::setbase(16) >> u;       /* convert hex to unsigned */
        msg.push_back((uint8_t)u);          /* add value as uint8_t */
    }

    std::cout << "string: " << result << "\nmsg: \n";
    for (auto& h : msg) /* for each element of msg, output hex value */
        std::cout << "\t" << std::setfill('0') << std::hex << std::setw(2) 
                    << (uint32_t)h << '\n';;
}

请注意,需要在输出中强制使用强制类型转换,以明确告诉coutuint8_t值视为unsigned值而不是{{1} }值,默认情况下默认为字符类型。

使用/输出示例

uint8_t

注意,这次存储了8个$ ./bin/hexstr2uint8_t string: 0123456789abcdef msg: 01 23 45 67 89 ab cd ef (“字节”)值,而不是16个字符值)

这只是使用C ++ iostream功能的一种替代方法,它避免了抛弃事物而不是直接调用uint8_t(开始时应该是strtol)的问题。

手动十六进制转换

在最后一条评论中,您指出使用iostream和stringstream进行转换很慢。您可以尝试通过消除字符串流并使用strtoul来逐步优化字符串,以手动完成每个字符串的转换,并逐步形成每个string::iterator字节(以防止出现最后的半字节或1/2) -byte),例如

uint8_t

(输出与上述相同)

如果您可以保证字符串中总是有偶数个字符(仅字节,最后一个奇数字符不为1/2字节),则可以通过删除条件并简单地使用以下方法来进一步优化: / p>

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

/* simple manual conversion of hexchar to value */
uint8_t c2hex (const char c)
{
    uint8_t u = 0;

    if ('0' <= c && c <= '9')
        u = c - '0';
    else if ('a' <= c && c <= 'f')
        u = c - 'W';
    else if ('A' <= c && c <= 'F')
        u = c - '7';
    else
        std::cerr << "error: invalid hex char '" << c << "'\n";

    return u;
}

int main (void) {

    std::string s ("0123456789abcdef");
    std::vector<uint8_t> msg;

    for (std::string::iterator n = s.begin(); n != s.end(); n += 2) {
        uint8_t u = c2hex (*n);             /* save high-nibble */
        if (n + 1 != s.end())               /* if low-nibble available */
            u = (u << 4) | c2hex (n[1]);    /* shift high left 4 & or */
        msg.push_back(u);                   /* store byte in msg */
    }

    std::cout << "string: " << s << "\nmsg:\n";
    for (auto& h : msg)
        std::cout << "\t" << std::setfill('0') << std::hex 
                    << std::setw(2) << (unsigned)h << '\n';
}

请确保您正在使用完整的优化进行编译,例如 uint8_t u = c2hex (n[1]) | (c2hex (*n) << 4); (或-O3 gcc版本> = 4.6)在gcc / clang上,-Ofast与VS。

考虑到性能的比较,您还可以将不同的版本转储到汇编中,看看那里是否还有其他提示。