programing

C의 바이트 배열에 대한 16진수 문자열

goodsources 2022. 7. 10. 21:24
반응형

C의 바이트 배열에 대한 16진수 문자열

16진수 문자열에서 바이트 배열로 변환하는 표준 C 함수가 있습니까?
나는 나만의 함수를 쓰고 싶지 않다.

표준 기능은 없는 것으로 알고 있습니다만, 다음과 같이 간단하게 실현할 수 있습니다.

#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이 지적한 바와 같이 스트링에 홀수 16진수가 포함되어 있는 경우에는 선두에 0을 붙여야 합니다.예를 들어 문자열은"f00f5"로 평가될 것이다.{0xf0, 0x0f, 0x05}상기의 예에 의해서, 적절한 것이 아니고,{0x0f, 0x00, 0xf5}.

@MassimoCallegari로부터의 코멘트에 대처하기 위해서, 예를 약간 수정했습니다.

구글링의 이 질문도 같은 질문으로 찾았습니다.sscanf()나 strtol()을 호출하는 것은 오버킬처럼 느껴지기 때문에 마음에 들지 않습니다.텍스트가 실제로 바이트 스트림의 16진수 표시인지는 검증되지 않지만 홀수 16진수를 처리하는 빠른 함수를 작성했습니다.

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);
}

위의 훌륭한 답변과는 별도로, 저는 라이브러리를 사용하지 않고 잘못된 문자열에 대한 가드가 있는 C 함수를 쓰려고 했습니다.

uint8_t* datahex(char* string) {

    if(string == NULL) 
       return NULL;

    size_t slength = strlen(string);
    if((slength % 2) != 0) // must be even
       return NULL;

    size_t dlength = slength / 2;

    uint8_t* data = malloc(dlength);
    memset(data, 0, dlength);

    size_t index = 0;
    while (index < slength) {
        char c = string[index];
        int value = 0;
        if(c >= '0' && c <= '9')
          value = (c - '0');
        else if (c >= 'A' && c <= 'F') 
          value = (10 + (c - 'A'));
        else if (c >= 'a' && c <= 'f')
          value = (10 + (c - 'a'));
        else {
          free(data);
          return NULL;
        }

        data[(index/2)] += value << (((index + 1) % 2) * 4);

        index++;
    }

    return data;
}

설명:

a. index / 2 | 정수 사이를 나누면 값이 반올림되므로 0/2 = 0, 1/2 = 0, 2/2 = 1, 3/2 = 1, 4/2 = 2, 5/2 = 2 등이 됩니다.따라서 2문자마다 1데이터 바이트에 값을 추가합니다.

b. (index + 1) % 2 | 16진수 문자열의 첫 번째 숫자가 가장 유의하고 16을 곱해야 하기 때문에 홀수 값이 1이 되고 짝수 값이 0이 됩니다.따라서 인덱스 0 = > 0 + 1% 2 = 0 등에 대해서는 인덱스 1 > 1 + 1% 2 = 0 등이 됩니다.

c. < < 4 | Shift x 4 는 16 을 곱하고 있습니다.예: b00000001 < 4 = b00010000

이 기능을 사용할 수 있습니다.

  1. (임베디드 프로세서의 경우) 퍼포먼스를 염두에 두고 작성되었으며,scanf,strtol또는dynamic memory allocation
  2. 출력 버퍼 오버플로 및 홀수 입력 스트렌에 대한 가드가 있음
/// in: valid chars are 0-9 + A-F + a-f
/// out_len_max==0: convert until the end of input string, out_len_max>0 only convert this many numbers
/// returns actual out size
int hexStr2Arr(unsigned char* out, const char* in, size_t out_len_max = 0)
{
    if (!out_len_max)
        out_len_max = 2147483647; // INT_MAX

    const int in_len = strnlen(in, out_len_max * 2);
    if (in_len % 2 != 0)
        return -1; // error, in str len should be even

    // calc actual out len
    const int out_len = out_len_max < (in_len / 2) ? out_len_max : (in_len / 2);

    for (int i = 0; i < out_len; i++) {
        char ch0 = in[2 * i];
        char ch1 = in[2 * i + 1];
        uint8_t nib0 = (ch0 & 0xF) + (ch0 >> 6) | ((ch0 >> 3) & 0x8);
        uint8_t nib1 = (ch1 & 0xF) + (ch1 >> 6) | ((ch1 >> 3) & 0x8);
        out[i] = (nib0 << 4) | nib1;
    }
    return out_len;
}

사용방법:

unsigned char result[128];
memset(result, 0, 128); // optional
printf("result len=%d\n", hexStr2Arr(result, "0a0B10"));  // result = [0A 0B 10 00 00 ...]

memset(result, 0, 128); // optional
// only convert single number
printf("result len=%d\n", hexStr2Arr(result, "0a0B10", 1)); // result = [0A 00 00 00 00 ...]

짧은 현의 경우strtol,strtoll,그리고.strtoimax(세 번째 인수는 스트링 처리에 사용하는 베이스임을 주의해 주세요.16)으로 설정합니다.입력이 다음보다 긴 경우number-of-bits-in-the-longest-integer-type/4다른 답변에서 제안하는 보다 유연한 방법 중 하나가 필요합니다.

일부 수정 양식 user411313의 코드에 따라 다음 사항이 적용됩니다.

#include <stdio.h>
#include <stdint.h> 
#include <string.h>

int main ()
{
    char *hexstring = "deadbeef10203040b00b1e50";
    int i;
    unsigned int bytearray[12];
    uint8_t str_len = strlen(hexstring);

    for (i = 0; i < (str_len / 2); i++) {
        sscanf(hexstring + 2*i, "%02x", &bytearray[i]);
        printf("bytearray %d: %02x\n", i, bytearray[i]);
    }

    return 0;
}

Michael Foukarakis 포스트의 살찐 버전(그 포스트에 코멘트를 추가할 "평판"이 아직 없기 때문에):

#include <stdio.h>
#include <string.h>

void print(unsigned char *byte_array, int byte_array_size)
{
    int i = 0;
    printf("0x");
    for(; i < byte_array_size; i++)
    {
        printf("%02x", byte_array[i]);
    }
    printf("\n");
}

int convert(const char *hex_str, unsigned char *byte_array, int byte_array_max)
{
    int hex_str_len = strlen(hex_str);
    int i = 0, j = 0;

    // The output array size is half the hex_str length (rounded up)
    int byte_array_size = (hex_str_len+1)/2;

    if (byte_array_size > byte_array_max)
    {
        // Too big for the output array
        return -1;
    }

    if (hex_str_len % 2 == 1)
    {
        // hex_str is an odd length, so assume an implicit "0" prefix
        if (sscanf(&(hex_str[0]), "%1hhx", &(byte_array[0])) != 1)
        {
            return -1;
        }

        i = j = 1;
    }

    for (; i < hex_str_len; i+=2, j++)
    {
        if (sscanf(&(hex_str[i]), "%2hhx", &(byte_array[j])) != 1)
        {
            return -1;
        }
    }

    return byte_array_size;
}

void main()
{
    char *examples[] = { "", "5", "D", "5D", "5Df", "deadbeef10203040b00b1e50", "02invalid55" };
    unsigned char byte_array[128];
    int i = 0;

    for (; i < sizeof(examples)/sizeof(char *); i++)
    {
        int size = convert(examples[i], byte_array, 128);
        if (size < 0)
        {
            printf("Failed to convert '%s'\n", examples[i]);
        }
        else if (size == 0)
        {
            printf("Nothing to convert for '%s'\n", examples[i]);
        }
        else
        {
            print(byte_array, size);
        }
    }
}

strchr()을 사용하여 바이트 또는 워드를 해석하는 두 개의 짧은 루틴.

// HexConverter.h
#ifndef HEXCONVERTER_H
#define HEXCONVERTER_H
unsigned int hexToByte (const char *hexString);
unsigned int hexToWord (const char *hexString);
#endif


// HexConverter.c
#include <string.h> // for strchr()
#include <ctype.h>  // for toupper()

unsigned int hexToByte (const char *hexString)
{
    unsigned int value;
    const char *hexDigits = "0123456789ABCDEF";

    value = 0;
    if (hexString != NULL)
    {
        char *ptr;

        ptr = strchr (hexDigits, toupper(hexString[0]));
        if (ptr != NULL)
        {
            value = (ptr - hexDigits) << 4;

            ptr = strchr (hexDigits, toupper(hexString[1]));
            if (ptr != NULL)
            {
                value = value | (ptr - hexDigits);
            }
        }
    }

    return value;
}

unsigned int hexToWord (const char *hexString)
{
    unsigned int value;

    value = 0;
    if (hexString != NULL)
    {
        value = (hexToByte (&hexString[0]) << 8) |
                (hexToByte (&hexString[2]));
    }

    return value;
}


// HexConverterTest.c
#include <stdio.h>

#include "HexConverter.h"

int main (int argc, char **argv)
{
    (void)argc; // not used
    (void)argv; // not used

    unsigned int value;
    char *hexString;

    hexString = "2a";
    value = hexToByte (hexString);
    printf ("%s == %x (%u)\n", hexString, value, value);

    hexString = "1234";
    value = hexToWord (hexString);
    printf ("%s == %x (%u)\n", hexString, value, value);

    hexString = "0102030405060708090a10ff";
    printf ("Hex String: %s\n", hexString);
    for (unsigned int idx = 0; idx < strlen(hexString); idx += 2)
    {
        value = hexToByte (&hexString[idx]);
        printf ("%c%c == %x (%u)\n", hexString[idx], hexString[idx+1],
                value, value);
    }

    return EXIT_SUCCESS;
}

퍼포먼스상의 이유로 작성한 솔루션은 다음과 같습니다.

void hex2bin(const char* in, size_t len, unsigned char* out) {

  static const unsigned char TBL[] = {
     0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  58,  59,  60,  61,
    62,  63,  64,  10,  11,  12,  13,  14,  15,  71,  72,  73,  74,  75,
    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
    90,  91,  92,  93,  94,  95,  96,  10,  11,  12,  13,  14,  15
  };

  static const unsigned char *LOOKUP = TBL - 48;

  const char* end = in + len;

  while(in < end) *(out++) = LOOKUP[*(in++)] << 4 | LOOKUP[*(in++)];

}

예:

unsigned char seckey[32];

hex2bin("351aaaec0070d13d350afae2bc43b68c7e590268889869dde489f2f7988f3fee", 64, seckey);

/*
  seckey = {
     53,  26, 170, 236,   0, 112, 209,  61,  53,  10, 250, 226, 188,  67, 182, 140, 
    126,  89,   2, 104, 136, 152, 105, 221, 228, 137, 242, 247, 152, 143,  63, 238
  };
*/

소문자를 지원할 필요가 없는 경우:

static const unsigned char TBL[] = {
     0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  58,  59,
    60,  61,  62,  63,  64,  10,  11,  12,  13,  14,  15
};

HexToBin과 BinToHex는 비교적 깔끔하고 읽기 쉬운 제품입니다.(원래 단순한 -1 또는 -2가 아닌 오류 로깅 시스템을 통해 Enum 오류 코드가 반환되었습니다.)

typedef unsigned char ByteData;
ByteData HexChar (char c)
{
    if ('0' <= c && c <= '9') return (ByteData)(c - '0');
    if ('A' <= c && c <= 'F') return (ByteData)(c - 'A' + 10);
    if ('a' <= c && c <= 'f') return (ByteData)(c - 'a' + 10);
    return (ByteData)(-1);
}

ssize_t HexToBin (const char* s, ByteData * buff, ssize_t length)
{
    ssize_t result = 0;
    if (!s || !buff || length <= 0) return -2;

    while (*s)
    {
        ByteData nib1 = HexChar(*s++);
        if ((signed)nib1 < 0) return -3;
        ByteData nib2 = HexChar(*s++);
        if ((signed)nib2 < 0) return -4;

        ByteData bin = (nib1 << 4) + nib2;

        if (length-- <= 0) return -5;
        *buff++ = bin;
        ++result;
    }
    return result;
}

void BinToHex (const ByteData * buff, ssize_t length, char * output, ssize_t outLength)
{
    char binHex[] = "0123456789ABCDEF";

    if (!output || outLength < 4) return (void)(-6);
    *output = '\0';

    if (!buff || length <= 0 || outLength <= 2 * length)
    {
        memcpy(output, "ERR", 4);
        return (void)(-7);
    }

    for (; length > 0; --length, outLength -= 2)
    {
        ByteData byte = *buff++;

        *output++ = binHex[(byte >> 4) & 0x0F];
        *output++ = binHex[byte & 0x0F];
    }
    if (outLength-- <= 0) return (void)(-8);
    *output++ = '\0';
}

hextools.h

#ifndef HEX_TOOLS_H
#define HEX_TOOLS_H

char *bin2hex(unsigned char*, int);

unsigned char *hex2bin(const char*);

#endif // HEX_TOOLS_H

hextools.c

#include <stdlib.h>

char *bin2hex(unsigned char *p, int len)
{
    char *hex = malloc(((2*len) + 1));
    char *r = hex;

    while(len && p)
    {
        (*r) = ((*p) & 0xF0) >> 4;
        (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r));
        r++;
        (*r) = ((*p) & 0x0F);
        (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r));
        r++;
        p++;
        len--;
    }
    *r = '\0';

    return hex;
}

unsigned char *hex2bin(const char *str)
{
    int len, h;
    unsigned char *result, *err, *p, c;

    err = malloc(1);
    *err = 0;

    if (!str)
        return err;

    if (!*str)
        return err;

    len = 0;
    p = (unsigned char*) str;
    while (*p++)
        len++;

    result = malloc((len/2)+1);
    h = !(len%2) * 4;
    p = result;
    *p = 0;

    c = *str;
    while(c)
    {
        if(('0' <= c) && (c <= '9'))
            *p += (c - '0') << h;
        else if(('A' <= c) && (c <= 'F'))
            *p += (c - 'A' + 10) << h;
        else if(('a' <= c) && (c <= 'f'))
            *p += (c - 'a' + 10) << h;
        else
            return err;

        str++;
        c = *str;

        if (h)
            h = 0;
        else
        {
            h = 4;
            p++;
            *p = 0;
        }
    }

    return result;
}

메인

#include <stdio.h>
#include "hextools.h"

int main(void)
{
    unsigned char s[] = { 0xa0, 0xf9, 0xc3, 0xde, 0x44 };

    char *hex = bin2hex(s, sizeof s);
    puts(hex);

    unsigned char *bin;
    bin = hex2bin(hex);

    puts(bin2hex(bin, 5));

    size_t k;
    for(k=0; k<5; k++)
        printf("%02X", bin[k]);

    putchar('\n');

    return 0;
}

이는 유사한 질문에서 수정된 함수로, https://stackoverflow.com/a/18267932/700597의 제안에 따라 수정되었습니다.

이 함수는 짝수 문자를 포함한 16진수 문자열('0x'가 앞에 없음)을 지정된 바이트 수로 변환합니다.유효하지 않은 문자가 발견되거나 16진수 문자열의 길이가 홀수일 경우 -1이 반환되고 성공 시 0이 반환됩니다.

//convert hexstring to len bytes of data
//returns 0 on success, -1 on error
//data is a buffer of at least len bytes
//hexstring is upper or lower case hexadecimal, NOT prepended with "0x"
int hex2data(unsigned char *data, const unsigned char *hexstring, unsigned int len)
{
    unsigned const char *pos = hexstring;
    char *endptr;
    size_t count = 0;

    if ((hexstring[0] == '\0') || (strlen(hexstring) % 2)) {
        //hexstring contains no data
        //or hexstring has an odd length
        return -1;
    }

    for(count = 0; count < len; count++) {
        char buf[5] = {'0', 'x', pos[0], pos[1], 0};
        data[count] = strtol(buf, &endptr, 0);
        pos += 2 * sizeof(char);

        if (endptr[0] != '\0') {
            //non-hexadecimal character encountered
            return -1;
        }
    }

    return 0;
}

아요를 사용해서 하는 것은 . 하지만 이 기술을 사용하는 것은 비교적 간단한 일입니다.sscanf고리를 틀어서.

char *hexstring = "deadbeef10203040b00b1e50", *pos = hexstring;
unsigned char val[12];
while( *pos )
{
  if( !((pos-hexstring)&1) )
    sscanf(pos,"%02x",&val[(pos-hexstring)>>1]);
  ++pos;
}

size of ( val ) / size of ( val [ 0 ] )는 용장입니다!

    In main()
    {
printf("enter string :\n");
    fgets(buf, 200, stdin);
unsigned char str_len = strlen(buf);
k=0;
unsigned char bytearray[100];
     for(j=0;j<str_len-1;j=j+2)
        { bytearray[k++]=converttohex(&buffer[j]);   
                printf(" %02X",bytearray[k-1]);
        }

    }

    Use this 

    int converttohex(char * val)
        {
        unsigned char temp = toupper(*val);
        unsigned char fin=0;
        if(temp>64)
        temp=10+(temp-65);

        else
        temp=temp-48;

        fin=(temp<<4)&0xf0;

        temp = toupper(*(val+1));

            if(temp>64)
            temp=10+(temp-65);

            else
            temp=temp-48;

        fin=fin|(temp & 0x0f);


           return fin;
        }

다음 코드를 사용해 보십시오.

static unsigned char ascii2byte(char *val)
{
    unsigned char temp = *val;

    if(temp > 0x60) temp -= 39;  // convert chars a-f
    temp -= 48;  // convert chars 0-9
    temp *= 16;

    temp += *(val+1);
    if(*(val+1) > 0x60) temp -= 39;  // convert chars a-f
    temp -= 48;  // convert chars 0-9   

    return temp;

}

내 버전은 다음과 같습니다.

/* Convert a hex char digit to its integer value. */
int hexDigitToInt(char digit) {
    digit = tolower(digit);
    if ('0' <= digit && digit <= '9') //if it's decimal
        return (int)(digit - '0');
    else if ('a' <= digit && digit <= 'f') //if it's abcdef
        return (int)(digit - ('a' - 10));
    else
        return -1; //value not in [0-9][a-f] range
}

/* Decode a hex string. */
char *decodeHexString(const char *hexStr) {
    char* decoded = malloc(strlen(hexStr)/2+1);
    char* hexStrPtr = (char *)hexStr;
    char* decodedPtr = decoded;

    while (*hexStrPtr != '\0') { /* Step through hexStr, two chars at a time. */
        *decodedPtr = 16 * hexDigitToInt(*hexStrPtr) + hexDigitToInt(*(hexStrPtr+1));
        hexStrPtr += 2;
        decodedPtr++;
    }

    *decodedPtr = '\0'; /* final null char */
    return decoded;
}

좀 더 쉽게 할 수 없을까?

uint8_t hex(char ch) {
    uint8_t r = (ch > 57) ? (ch - 55) : (ch - 48);
    return r & 0x0F;
}

int to_byte_array(const char *in, size_t in_size, uint8_t *out) {
    int count = 0;
    if (in_size % 2) {
        while (*in && out) {
            *out = hex(*in++);
            if (!*in)
                return count;
            *out = (*out << 4) | hex(*in++);
            *out++;
            count++;
        }
        return count;
    } else {
        while (*in && out) {
            *out++ = (hex(*in++) << 4) | hex(*in++);
            count++;
        }
        return count;
    }
}

int main() {
    char hex_in[] = "deadbeef10203040b00b1e50";
    uint8_t out[32];
    int res = to_byte_array(hex_in, sizeof(hex_in) - 1, out);

    for (size_t i = 0; i < res; i++)
        printf("%02x ", out[i]);

    printf("\n");
    system("pause");
    return 0;
}

내가 아는 가장 좋은 방법은:

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"

01 02 03 04 ab cd ef 를 포함한 dest_dest로 변환됩니다.

또한 "01020304abCdeFgarbage"AB"

이전과 같이 변환됩니다.

첫 번째 "오류"에서 구문 분석이 중지됩니다.

여기 파일 처리 방법이 있습니다. 더 자주 사용할 수 있습니다.

int convert(char *infile, char *outfile) {

char *source = NULL;
FILE *fp = fopen(infile, "r");
long bufsize;
if (fp != NULL) {
    /* Go to the end of the file. */
    if (fseek(fp, 0L, SEEK_END) == 0) {
        /* Get the size of the file. */
        bufsize = ftell(fp);
        if (bufsize == -1) { /* Error */ }

        /* Allocate our buffer to that size. */
        source = malloc(sizeof(char) * (bufsize + 1));

        /* Go back to the start of the file. */
        if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }

        /* Read the entire file into memory. */
        size_t newLen = fread(source, sizeof(char), bufsize, fp);
        if ( ferror( fp ) != 0 ) {
            fputs("Error reading file", stderr);
        } else {
            source[newLen++] = '\0'; /* Just to be safe. */
        }
    }
    fclose(fp);
}
     
int sourceLen = bufsize - 1;
int destLen = sourceLen/2;
unsigned char* dest = malloc(destLen);
short i;  
unsigned char highByte, lowByte;  
      
for (i = 0; i < sourceLen; i += 2)  
{  
        highByte = toupper(source[i]);  
        lowByte  = toupper(source[i + 1]);  
  
        if (highByte > 0x39)  
            highByte -= 0x37;  
        else  
            highByte -= 0x30;  
  
        if (lowByte > 0x39)  
            lowByte -= 0x37;  
        else  
            lowByte -= 0x30;  
  
        dest[i / 2] = (highByte << 4) | lowByte;  
}  
        

FILE *fop = fopen(outfile, "w");
if (fop == NULL) return 1;
fwrite(dest, 1, destLen, fop);
fclose(fop);
free(source);
free(dest);
return 0;
}  

언급URL : https://stackoverflow.com/questions/3408706/hexadecimal-string-to-byte-array-in-c

반응형