为了账号安全,请及时绑定邮箱和手机立即绑定

十六进制字符串到C中的字节数组

十六进制字符串到C中的字节数组

C
慕尼黑的夜晚无繁华 2019-11-13 15:41:38
是否有标准的C函数将十六进制字符串转换为字节数组?我不想编写自己的函数。
查看完整描述

3 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

据我所知,尚无标准功能,但可以通过以下方式轻松实现:


#include <stdio.h>


int main(int argc, char **argv) {

    const char hexstring[] = "DEadbeef10203040b00b1e50", *pos = hexstring;

    unsigned char val[12];


     /* WARNING: no sanitization or error-checking whatsoever */

    for (size_t count = 0; count < sizeof val/sizeof *val; count++) {

        sscanf(pos, "%2hhx", &val[count]);

        pos += 2;

    }


    printf("0x");

    for(size_t count = 0; count < sizeof val/sizeof *val; count++)

        printf("%02x", val[count]);

    printf("\n");


    return 0;

}

编辑

正如Al所指出的那样,如果字符串中的十六进制数字为奇数,则必须确保以0开头。例如, 上面的示例"f00f5"将字符串{0xf0, 0x0f, 0x05}错误地评估为字符串,而不是正确的字符串。{0x0f, 0x00, 0xf5}。


稍微修改了示例以解决@MassimoCallegari的评论


查看完整回答
反对 回复 2019-11-13
?
LEATH

TA贡献1936条经验 获得超6个赞

我通过谷歌搜索发现了同样的问题。我不喜欢调用sscanf()或strtol()的想法,因为它感觉像是过分杀了。我编写了一个快速函数,该函数不能验证文本确实是字节流的十六进制表示形式,但是可以处理奇数个十六进制数字:


uint8_t tallymarker_hextobin(const char * str, uint8_t * bytes, size_t blen)

{

   uint8_t  pos;

   uint8_t  idx0;

   uint8_t  idx1;


   // mapping of ASCII characters to hex values

   const uint8_t hashmap[] =

   {

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  !"#$%&'

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ()*+,-./

     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567

     0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?

     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_

     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pqrstuvw

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xyz{|}~.

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........

     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // ........

   };


   bzero(bytes, blen);

   for (pos = 0; ((pos < (blen*2)) && (pos < strlen(str))); pos += 2)

   {

      idx0 = (uint8_t)str[pos+0];

      idx1 = (uint8_t)str[pos+1];

      bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1];

   };


   return(0);

}


查看完整回答
反对 回复 2019-11-13
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

对于短字符串,strtolstrtoll,并且strtoimax将工作得很好(请注意,第三个参数是基地在使用处理字符串...它设置为16)。如果您的输入时间长于此,number-of-bits-in-the-longest-integer-type/4那么您将需要其他答案建议的一种更灵活的方法。


查看完整回答
反对 回复 2019-11-13
  • 3 回答
  • 0 关注
  • 534 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信