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

发布于 2024-08-07 07:23:49 字数 160 浏览 8 评论 0原文

给定一串十六进制值 ie 例如“0011223344”,即 0x00、0x11 等。

如何将这些值添加到 char 数组中?

相当于说:

char array[4] = { 0x00, 0x11 ... };

Given a string of hex values i.e. e.g. "0011223344" so that's 0x00, 0x11 etc.

How do I add these values to a char array?

Equivalent to say:

char array[4] = { 0x00, 0x11 ... };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

女中豪杰 2024-08-14 07:23:49

您无法将 5 个字节的数据放入 4 个字节的数组中;这会导致缓冲区溢出。

如果字符串中有十六进制数字,则可以使用 sscanf() 和循环:

#include <stdio.h>
#include <ctype.h>

int main()
{
    const char *src = "0011223344";
    char buffer[5];
    char *dst = buffer;
    char *end = buffer + sizeof(buffer);
    unsigned int u;

    while (dst < end && sscanf(src, "%2x", &u) == 1)
    {
        *dst++ = u;
        src += 2;
    }

    for (dst = buffer; dst < end; dst++)
        printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
               (isprint(*dst) ? *dst : '.'), *dst, *dst);

    return(0);
}

请注意,打印以零字节开头的字符串需要小心;大多数操作在第一个空字节处终止。请注意,此代码并未以空值终止缓冲区;目前尚不清楚是否需要空终止,并且我声明的缓冲区中没有足够的空间来添加终端空(但这很容易修复)。如果代码被打包为子例程,则很有可能需要返回转换后的字符串的长度(尽管您也可以认为它是源字符串的长度除以二)。

You can't fit 5 bytes worth of data into a 4 byte array; that leads to buffer overflows.

If you have the hex digits in a string, you can use sscanf() and a loop:

#include <stdio.h>
#include <ctype.h>

int main()
{
    const char *src = "0011223344";
    char buffer[5];
    char *dst = buffer;
    char *end = buffer + sizeof(buffer);
    unsigned int u;

    while (dst < end && sscanf(src, "%2x", &u) == 1)
    {
        *dst++ = u;
        src += 2;
    }

    for (dst = buffer; dst < end; dst++)
        printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
               (isprint(*dst) ? *dst : '.'), *dst, *dst);

    return(0);
}

Note that printing the string starting with a zero-byte requires care; most operations terminate on the first null byte. Note that this code did not null-terminate the buffer; it is not clear whether null-termination is desirable, and there isn't enough space in the buffer I declared to add a terminal null (but that is readily fixed). There's a decent chance that if the code was packaged as a subroutine, it would need to return the length of the converted string (though you could also argue it is the length of the source string divided by two).

南城旧梦 2024-08-14 07:23:49

我会做这样的事情;

// Convert from ascii hex representation to binary
// Examples;
//   "00" -> 0
//   "2a" -> 42
//   "ff" -> 255
// Case insensitive, 2 characters of input required, no error checking
int hex2bin( const char *s )
{
    int ret=0;
    int i;
    for( i=0; i<2; i++ )
    {
        char c = *s++;
        int n=0;
        if( '0'<=c && c<='9' )
            n = c-'0';
        else if( 'a'<=c && c<='f' )
            n = 10 + c-'a';
        else if( 'A'<=c && c<='F' )
            n = 10 + c-'A';
        ret = n + ret*16;
    }
    return ret;
}

int main()
{
    const char *in = "0011223344";
    char out[5];
    int i;

    // Hex to binary conversion loop. For example;
    // If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44}
    for( i=0; i<5; i++ )
    {
        out[i] = hex2bin( in );
        in += 2;
    }
    return 0;
}

I would do something like this;

// Convert from ascii hex representation to binary
// Examples;
//   "00" -> 0
//   "2a" -> 42
//   "ff" -> 255
// Case insensitive, 2 characters of input required, no error checking
int hex2bin( const char *s )
{
    int ret=0;
    int i;
    for( i=0; i<2; i++ )
    {
        char c = *s++;
        int n=0;
        if( '0'<=c && c<='9' )
            n = c-'0';
        else if( 'a'<=c && c<='f' )
            n = 10 + c-'a';
        else if( 'A'<=c && c<='F' )
            n = 10 + c-'A';
        ret = n + ret*16;
    }
    return ret;
}

int main()
{
    const char *in = "0011223344";
    char out[5];
    int i;

    // Hex to binary conversion loop. For example;
    // If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44}
    for( i=0; i<5; i++ )
    {
        out[i] = hex2bin( in );
        in += 2;
    }
    return 0;
}
圈圈圆圆圈圈 2024-08-14 07:23:49

如果字符串是正确的并且不需要保留其内容,那么我会这样做:

#define hex(c) ((*(c)>='a')?*(c)-'a'+10:(*(c)>='A')?*(c)-'A'+10:*(c)-'0') 

void hex2char( char *to ){
  for(char *from=to; *from; from+=2) *to++=hex(from)*16+hex(from+1);
  *to=0;
}

编辑 1:抱歉,我忘记用字母 AF (af) 进行计算

编辑 2:我尝试编写更迂腐的代码:

#include <string.h> 

int xdigit( char digit ){
  int val;
       if( '0' <= digit && digit <= '9' ) val = digit -'0';
  else if( 'a' <= digit && digit <= 'f' ) val = digit -'a'+10;
  else if( 'A' <= digit && digit <= 'F' ) val = digit -'A'+10;
  else                                    val = -1;
  return val;
}

int xstr2str( char *buf, unsigned bufsize, const char *in ){
  if( !in ) return -1; // missing input string

  unsigned inlen=strlen(in);
  if( inlen%2 != 0 ) return -2; // hex string must even sized

  for( unsigned i=0; i<inlen; i++ )
    if( xdigit(in[i])<0 ) return -3; // bad character in hex string

  if( !buf || bufsize<inlen/2+1 ) return -4; // no buffer or too small

  for( unsigned i=0,j=0; i<inlen; i+=2,j++ )
    buf[j] = xdigit(in[i])*16 + xdigit(in[i+1]);

  buf[inlen/2] = '\0';
  return inlen/2+1;
}

测试:

#include <stdio.h> 

char buf[100] = "test";

void test( char *buf, const char *s ){
   printf("%3i=xstr2str( \"%s\", 100, \"%s\" )\n", xstr2str( buf, 100, s ), buf, s );
}

int main(){
  test( buf,      (char*)0   );
  test( buf,      "123"      );
  test( buf,      "3x"       );
  test( (char*)0, ""         );
  test( buf,      ""         );
  test( buf,      "3C3e"     );
  test( buf,      "3c31323e" );

  strcpy( buf,    "616263"   ); test( buf, buf );
}

结果:

 -1=xstr2str( "test", 100, "(null)" )
 -2=xstr2str( "test", 100, "123" )
 -3=xstr2str( "test", 100, "3x" )
 -4=xstr2str( "(null)", 100, "" )
  1=xstr2str( "", 100, "" )
  3=xstr2str( "", 100, "3C3e" )
  5=xstr2str( "", 100, "3c31323e" )
  4=xstr2str( "abc", 100, "abc" )

If the string is correct and no need to keep its content then i would do it this way:

#define hex(c) ((*(c)>='a')?*(c)-'a'+10:(*(c)>='A')?*(c)-'A'+10:*(c)-'0') 

void hex2char( char *to ){
  for(char *from=to; *from; from+=2) *to++=hex(from)*16+hex(from+1);
  *to=0;
}

EDIT 1: sorry, i forget to calculate with the letters A-F (a-f)

EDIT 2: i tried to write a more pedantic code:

#include <string.h> 

int xdigit( char digit ){
  int val;
       if( '0' <= digit && digit <= '9' ) val = digit -'0';
  else if( 'a' <= digit && digit <= 'f' ) val = digit -'a'+10;
  else if( 'A' <= digit && digit <= 'F' ) val = digit -'A'+10;
  else                                    val = -1;
  return val;
}

int xstr2str( char *buf, unsigned bufsize, const char *in ){
  if( !in ) return -1; // missing input string

  unsigned inlen=strlen(in);
  if( inlen%2 != 0 ) return -2; // hex string must even sized

  for( unsigned i=0; i<inlen; i++ )
    if( xdigit(in[i])<0 ) return -3; // bad character in hex string

  if( !buf || bufsize<inlen/2+1 ) return -4; // no buffer or too small

  for( unsigned i=0,j=0; i<inlen; i+=2,j++ )
    buf[j] = xdigit(in[i])*16 + xdigit(in[i+1]);

  buf[inlen/2] = '\0';
  return inlen/2+1;
}

Testing:

#include <stdio.h> 

char buf[100] = "test";

void test( char *buf, const char *s ){
   printf("%3i=xstr2str( \"%s\", 100, \"%s\" )\n", xstr2str( buf, 100, s ), buf, s );
}

int main(){
  test( buf,      (char*)0   );
  test( buf,      "123"      );
  test( buf,      "3x"       );
  test( (char*)0, ""         );
  test( buf,      ""         );
  test( buf,      "3C3e"     );
  test( buf,      "3c31323e" );

  strcpy( buf,    "616263"   ); test( buf, buf );
}

Result:

 -1=xstr2str( "test", 100, "(null)" )
 -2=xstr2str( "test", 100, "123" )
 -3=xstr2str( "test", 100, "3x" )
 -4=xstr2str( "(null)", 100, "" )
  1=xstr2str( "", 100, "" )
  3=xstr2str( "", 100, "3C3e" )
  5=xstr2str( "", 100, "3c31323e" )
  4=xstr2str( "abc", 100, "abc" )
久光 2024-08-14 07:23:49

我一直在寻找同样的东西,经过大量阅读后,终于创建了这个函数。认为这可能有帮助,有人

// in = "63 09  58  81" 
void hexatoascii(char *in, char* out, int len){
    char buf[5000];
    int i,j=0;
    char * data[5000];
    printf("\n size %d", strlen(in));
    for (i = 0; i < strlen(in); i+=2)
    {
        data[j] = (char*)malloc(8);
        if (in[i] == ' '){
            i++;
        }
        else if(in[i + 1] == ' '){
            i++;
        }
        printf("\n %c%c", in[i],in[i+1]);
        sprintf(data[j], "%c%c", in[i], in[i+1]);
        j++;
    }

    for (i = 0; i < j-1; i++){
        int tmp;
        printf("\n data %s", data[i] );
        sscanf(data[i], "%2x", &tmp);
        out[i] = tmp;
    }
    //printf("\n ascii value of hexa %s", out);
}

I was searching for the same thing and after reading a lot, finally created this function. Thought it might help, someone

// in = "63 09  58  81" 
void hexatoascii(char *in, char* out, int len){
    char buf[5000];
    int i,j=0;
    char * data[5000];
    printf("\n size %d", strlen(in));
    for (i = 0; i < strlen(in); i+=2)
    {
        data[j] = (char*)malloc(8);
        if (in[i] == ' '){
            i++;
        }
        else if(in[i + 1] == ' '){
            i++;
        }
        printf("\n %c%c", in[i],in[i+1]);
        sprintf(data[j], "%c%c", in[i], in[i+1]);
        j++;
    }

    for (i = 0; i < j-1; i++){
        int tmp;
        printf("\n data %s", data[i] );
        sscanf(data[i], "%2x", &tmp);
        out[i] = tmp;
    }
    //printf("\n ascii value of hexa %s", out);
}
岁月打碎记忆 2024-08-14 07:23:49

假设这是一个小端 ascii 平台。
也许OP的意思是“字符数组”而不是“字符串”。
我们使用成对的字符和位掩码..注意x16的转变..

/* not my original work, on stacko somewhere ? */

for (i=0;i < 4;i++) {

    char a = string[2 * i];
    char b = string[2 * i + 1];

    array[i] = (((encode(a) * 16) & 0xF0) + (encode(b) & 0x0F));
 }

并且定义了函数encode()...

unsigned char encode(char x) {     /* Function to encode a hex character */
/****************************************************************************
 * these offsets should all be decimal ..x validated for hex..              *
 ****************************************************************************/
    if (x >= '0' && x <= '9')         /* 0-9 is offset by hex 30 */
        return (x - 0x30);
    else if (x >= 'a' && x <= 'f')    /* a-f offset by hex 57 */
        return(x - 0x57);
    else if (x >= 'A' && x <= 'F')    /* A-F offset by hex 37 */
        return(x - 0x37);
}

这种方法在其他地方漂浮,它不是我的原创作品,但它是旧的。
纯粹主义者不喜欢它,因为它不可移植,但扩展也很简单。

Let's say this is a little-endian ascii platform.
Maybe the OP meant "array of char" rather than "string"..
We work with pairs of char and bit masking.. note shiftyness of x16..

/* not my original work, on stacko somewhere ? */

for (i=0;i < 4;i++) {

    char a = string[2 * i];
    char b = string[2 * i + 1];

    array[i] = (((encode(a) * 16) & 0xF0) + (encode(b) & 0x0F));
 }

and function encode() is defined...

unsigned char encode(char x) {     /* Function to encode a hex character */
/****************************************************************************
 * these offsets should all be decimal ..x validated for hex..              *
 ****************************************************************************/
    if (x >= '0' && x <= '9')         /* 0-9 is offset by hex 30 */
        return (x - 0x30);
    else if (x >= 'a' && x <= 'f')    /* a-f offset by hex 57 */
        return(x - 0x57);
    else if (x >= 'A' && x <= 'F')    /* A-F offset by hex 37 */
        return(x - 0x37);
}

This approach floats around elsewhere, it is not my original work, but it is old.
Not liked by the purists because it is non-portable, but extension would be trivial.

Bonjour°[大白 2024-08-14 07:23:49

我知道的最好方法:

int hex2bin_by_zibri(char *source_str, char *dest_buffer)
{
  char *line = source_str;
  char *data = line;
  int offset;
  int read_byte;
  int data_len = 0;

  while (sscanf(data, " %02x%n", &read_byte, &offset) == 1) {
    dest_buffer[data_len++] = read_byte;
    data += offset;
  }
  return data_len;
}

该函数返回 dest_buffer 中保存的转换字节数。
输入字符串可以包含空格和大小写混合的字母。

“01 02 03 04 ab Cd eF 垃圾 AB”

转换为 dest_buffer 包含
01 02 03 04 ab cd ef

以及
“01020304abCdeFgarbageAB”

的翻译如前。

解析在第一个“错误”处停止(非十六进制,非空格)。

注意:这也是一个有效的字符串:

“01 2 03 04 ab Cd eF 垃圾 AB”

并产生:

01 02 03 04 ab cd ef

The best way I know:

int hex2bin_by_zibri(char *source_str, char *dest_buffer)
{
  char *line = source_str;
  char *data = line;
  int offset;
  int read_byte;
  int data_len = 0;

  while (sscanf(data, " %02x%n", &read_byte, &offset) == 1) {
    dest_buffer[data_len++] = read_byte;
    data += offset;
  }
  return data_len;
}

The function returns the number of converted bytes saved in dest_buffer.
The input string can contain spaces and mixed case letters.

"01 02 03 04 ab Cd eF garbage AB"

translates to dest_buffer containing
01 02 03 04 ab cd ef

and also
"01020304abCdeFgarbageAB"

translates as before.

Parsing stops at the first "error" (non hex, non space).

Note: also this is a valid string:

"01 2 03 04 ab Cd eF garbage AB"

and produces:

01 02 03 04 ab cd ef

孤者何惧 2024-08-14 07:23:49

Fatalfloor...

有几种方法可以做到这一点...首先,您可以使用 memcpy() 将精确表示复制到 char 数组中。

您也可以使用位移位和位屏蔽技术。我猜这就是你需要做的,因为这听起来像是一个家庭作业问题。

最后,您可以使用一些奇特的指针间接来复制您需要的内存位置。

所有这些方法的详细信息如下:

将 int 存储在 char 数组中?

Fatalfloor...

There are a couple of ways to do this... first, you can use memcpy() to copy the exact representation into the char array.

You can use bit shifting and bit masking techniques as well. I'm guessing this is what you need to do as it sounds like a homework problem.

Lastly, you can use some fancy pointer indirection to copy the memory location you need.

All of these methods are detailed here:

Store an int in a char array?

紫竹語嫣☆ 2024-08-14 07:23:49

给出一个最好的方法:

十六进制字符串转数值,即str[] = "0011223344"转值为0x0011223344,使用

value = strtoul(string, NULL, 16); // or strtoull()

done。如果需要删除开头的 0x00,请参见下文。

但对于 LITTLE_ENDIAN 平台,加上:
十六进制值到 char 数组,值 0x11223344 到 char arr[N] = {0x00, 0x11, ...}

unsigned long *hex = (unsigned long*)arr;
*hex = htonl(value);
// you'd like to remove any beginning 0x00
char *zero = arr;
while (0x00 == *zero) { zero++; }
if (zero > arr) memmove(zero, arr, sizeof(arr) - (zero - arr));

完成。

笔记:
为了在 32 位系统上将长字符串转换为 64 位十六进制 char arr,您应该使用 unsigned long long 而不是 unsigned long,并且 htonl 还不够,所以请按照下面的方式自行操作,因为可能没有 htonll、htonq 或 hton64等:

#if __KERNEL__
    /* Linux Kernel space */
    #if defined(__LITTLE_ENDIAN_BITFIELD)
        #define hton64(x)   __swab64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif defined(__GNUC__)
    /* GNU, user space */
    #if __BYTE_ORDER == __LITTLE_ENDIAN 
        #define hton64(x)   __bswap_64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif 
         ...
#endif

#define ntoh64(x)   hton64(x)

请参阅 http:// /effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h

Give a best way:

Hex string to numeric value , i.e. str[] = "0011223344" to value 0x0011223344, use

value = strtoul(string, NULL, 16); // or strtoull()

done. if need remove beginning 0x00, see below.

though for LITTLE_ENDIAN platforms, plus:
Hex value to char array, value 0x11223344 to char arr[N] = {0x00, 0x11, ...}

unsigned long *hex = (unsigned long*)arr;
*hex = htonl(value);
// you'd like to remove any beginning 0x00
char *zero = arr;
while (0x00 == *zero) { zero++; }
if (zero > arr) memmove(zero, arr, sizeof(arr) - (zero - arr));

done.

Notes:
For converting long string to a 64 bits hex char arr on a 32-bit system, you should use unsigned long long instead of unsigned long, and htonl is not enough, so do it yourself as below because might there's no htonll, htonq or hton64 etc:

#if __KERNEL__
    /* Linux Kernel space */
    #if defined(__LITTLE_ENDIAN_BITFIELD)
        #define hton64(x)   __swab64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif defined(__GNUC__)
    /* GNU, user space */
    #if __BYTE_ORDER == __LITTLE_ENDIAN 
        #define hton64(x)   __bswap_64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif 
         ...
#endif

#define ntoh64(x)   hton64(x)

see http://effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h

情域 2024-08-14 07:23:49
{
    char szVal[] = "268484927472";
    char szOutput[30];

    size_t nLen = strlen(szVal);
    // Make sure it is even.
    if ((nLen % 2) == 1)
    {
        printf("Error string must be even number of digits %s", szVal);
    }

    // Process each set of characters as a single character.
    nLen >>= 1;
    for (size_t idx = 0; idx < nLen; idx++)
    {
        char acTmp[3];
        sscanf(szVal + (idx << 1), "%2s", acTmp);
        szOutput[idx] = (char)strtol(acTmp, NULL, 16);
    }
}
{
    char szVal[] = "268484927472";
    char szOutput[30];

    size_t nLen = strlen(szVal);
    // Make sure it is even.
    if ((nLen % 2) == 1)
    {
        printf("Error string must be even number of digits %s", szVal);
    }

    // Process each set of characters as a single character.
    nLen >>= 1;
    for (size_t idx = 0; idx < nLen; idx++)
    {
        char acTmp[3];
        sscanf(szVal + (idx << 1), "%2s", acTmp);
        szOutput[idx] = (char)strtol(acTmp, NULL, 16);
    }
}
灼痛 2024-08-14 07:23:49

下面是我的 hex2binbin2hex 实现。

这些函数:

  • 是公共领域(可以随意复制和粘贴)
  • 很简单
  • 是正确的(即经过测试)
  • 执行错误处理(-1 表示无效的十六进制字符串)

hex2bin

static char h2b(char c) {
    return '0'<=c && c<='9' ? c - '0'      :
           'A'<=c && c<='F' ? c - 'A' + 10 :
           'a'<=c && c<='f' ? c - 'a' + 10 :
           /* else */         -1;
}

int hex2bin(unsigned char* bin,  unsigned int bin_len, const char* hex) {
    for(unsigned int i=0; i<bin_len; i++) {
        char b[2] = {h2b(hex[2*i+0]), h2b(hex[2*i+1])};
        if(b[0]<0 || b[1]<0) return -1;
        bin[i] = b[0]*16 + b[1];
    }
    return 0;
}

bin2hex

static char b2h(unsigned char b, int upper) {
    return b<10 ? '0'+b : (upper?'A':'a')+b-10;
}

void bin2hex(char* hex, const unsigned char* bin, unsigned int bin_len, int upper) {
    for(unsigned int i=0; i<bin_len; i++) {
        hex[2*i+0] = b2h(bin[i]>>4,   upper);
        hex[2*i+1] = b2h(bin[i]&0x0F, upper);
    }
}

Below are my hex2bin and bin2hex implementations.

These functions:

  • Are public domain (feel free to copy and paste)
  • Are simple
  • Are correct (i.e., tested)
  • Perform error handling (-1 means invalid hex string)

hex2bin

static char h2b(char c) {
    return '0'<=c && c<='9' ? c - '0'      :
           'A'<=c && c<='F' ? c - 'A' + 10 :
           'a'<=c && c<='f' ? c - 'a' + 10 :
           /* else */         -1;
}

int hex2bin(unsigned char* bin,  unsigned int bin_len, const char* hex) {
    for(unsigned int i=0; i<bin_len; i++) {
        char b[2] = {h2b(hex[2*i+0]), h2b(hex[2*i+1])};
        if(b[0]<0 || b[1]<0) return -1;
        bin[i] = b[0]*16 + b[1];
    }
    return 0;
}

bin2hex

static char b2h(unsigned char b, int upper) {
    return b<10 ? '0'+b : (upper?'A':'a')+b-10;
}

void bin2hex(char* hex, const unsigned char* bin, unsigned int bin_len, int upper) {
    for(unsigned int i=0; i<bin_len; i++) {
        hex[2*i+0] = b2h(bin[i]>>4,   upper);
        hex[2*i+1] = b2h(bin[i]&0x0F, upper);
    }
}
若无相欠,怎会相见 2024-08-14 07:23:49

首先,你的问题问得不太准确。该字符串是 std::string 还是 char 缓冲区?编译时设置?

动态内存几乎肯定是您的答案。

char* arr = (char*)malloc(numberOfValues);

然后,您可以遍历输入并将其分配给数组。

First, your question isn't very precise. Is the string a std::string or a char buffer? Set at compile-time?

Dynamic memory is almost certainly your answer.

char* arr = (char*)malloc(numberOfValues);

Then, you can walk through the input, and assign it to the array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文