简体   繁体   English

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

[英]Hex_string to uint8_t msg[]

I want convert the characters in hex string 我想转换十六进制字符串中的字符

"0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98" 

to uint8_t msg[] and do not understand how to do it. uint8_t msg[]并且不知道该怎么做。

It seems simple, but have been unable to figure it out. 看起来很简单,但一直无法弄清楚。 I want to convert each character to a uint8_t hex value. 我想将每个字符转换为uint8_t十六进制值。 For example if I have 例如,如果我有

string result = "0123456789abcdef";

How do I convert the string to: 如何将字符串转换为:

uint8_t msg[] = "0123456789abcdef";

This func (thanks Converting a hex string to a byte array ) 此函数(感谢将十六进制字符串转换为字节数组

vector<uint8_t> HexToBytes(const string& hex) {
  vector<uint8_t> bytes;
  for (unsigned int i = 0; i < hex.length(); i += 2) {
    string byteString = hex.substr(i, 2);
    uint8_t byte = (uint8_t) strtol(byteString.c_str(), nullptr, 16);
    bytes.push_back(byte);
  }
  return bytes;
}

using the above function we get the vector of bytes and call the method data() 使用上面的函数,我们获得字节向量,并调用方法data()

I want to thank the community now everything is working correctly. 我要感谢社区,现在一切正常。 Thanks for the comments, I was already desperate that I could not do such a simple thing. 感谢您的评论,我已经迫切希望做不到这么简单的事情。 Special thanks to @johnny-mopp 特别感谢@ johnny-mopp

Edit - Updated to ready bytes not characters 编辑-更新为就绪字节而不是字符

Rather than using .substr() and calling C strtol and casting to uint8_t , you can simply use an istringstream along with std::setbase(16) to read the bytes as unsigned values directly into your vector<uint8_t> msg . .substr()使用.substr()并调用C strtol并将其强制转换为uint8_t ,您只需将istringstreamstd::setbase(16)一起使用, istringstreamunsigned值的字节直接读取到vector<uint8_t> msg See std::setbase . 参见std :: setbase

For instance you can create an istringstream from your string containing the hex characters, and then along with your vector of uint8_t and a temporary unsigned to read directly into before pushing back into your vector you could do, eg 例如,您可以从包含十六进制字符的字符串中创建一个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 */
    }

In that way, each 2 characters in result read using std::setw(2) are used to create a 2-character stringstream that is then converted a an unsigned value using std::setbase(16) . 这样,使用std::setw(2)读取的result每个2个字符将用于创建2个字符的字符串流,然后使用std::setbase(16)将其转换为unsigned值。 A complete example would be: 一个完整的例子是:

#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';;
}

( note the cast required in the output to explicitly tell cout to treat the uint8_t value as an unsigned value rather than a uint8_t value which defaults to an character type by default. 请注意 ,输出中需要使用cout转换,以明确告知coutuint8_t值视为unsigned值,而不是默认为字符类型的uint8_t值。

Example Use/Output 使用/输出示例

$ ./bin/hexstr2uint8_t
string: 0123456789abcdef
msg:
        01
        23
        45
        67
        89
        ab
        cd
        ef

( note there are 8 uint8_t ("byte") values stored this time instead of 16 character values) 请注意 ,这次存储了8个uint8_t (“字节”)值,而不是16个字符值)

It's just an alternative using the C++ iostream features which avoids the need to cast things around rather than calling strtol directly (which in your case should probably be strtoul to begin with). 这只是其中使用避免了需要转换的东西,而不是周围调用C ++的iostream功能替代strtol直接(在你的情况可能应该strtoul开始与)。

Manual Hex Conversion 手动十六进制转换

In your last comment you indicate that using iostream and stringstream for the conversion is slow. 在最后一条评论中,您指出使用iostream和stringstream进行转换很慢。 You can attempt to optimize a bit by eliminating the stringstream and using a string::iterator to step through the string manually converting each character and forming each uint8_t byte as you go (protecting against a final nibble or 1/2-byte), eg 您可以尝试通过消除string::iterator并使用string::iterator来逐步优化字符串,以手动转换每个字符并uint8_t形成每个uint8_t字节(以防止出现最后的半字节或1/2字节),例如

#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';
}

(output is the same as above) (输出与上面相同)

If you can guarantee there will always be an even number of characters in your string (bytes only and no 1/2-byte as the final-odd character), you can further optimize by removing the conditional and simply using: 如果可以保证字符串中始终有偶数个字符(仅字节,最后一个奇数字符不为1/2字节),则可以通过删除条件并简单地使用以下命令来进一步优化:

        uint8_t u = c2hex (n[1]) | (c2hex (*n) << 4);

Make sure you are compiling with full optimization, eg -O3 (or -Ofast gcc version >= 4.6) on gcc/clang and /Ox with VS. 请确保您有充分优化的编译,如-O3 (或-Ofast上的gcc /铛gcc版本> = 4.6)和/Ox与VS.

Give that a try and compare performance, you can additionally dump the differing versions to assembly and see if there are any additional hints there. 尝试比较性能,您还可以将不同的版本转储到汇编中,看看那里是否还有其他提示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM