3

I have found a whole lot of different solutions to this problem, but not all of them work, and a lot of them seem somewhat hacky and inefficient. Basically I have a string of hexadecimal data (i.e. "55 AA 41 2A 00 94 55 AA BB BB 00 FF") which I would like to convert to raw data. What is the best way to do this?

UPDATE: Vicky's solution worked great for me, but I changed it to work with hexadecimal strings that don't have spaces in between and changed the style a bit.

int i = 0;
char *hexString = "55AA412A009455AABBBB00FF"
char *hexPtr = hexString;
unsigned int *result = calloc(strlen(hexString)/2 + 1, sizeof *result);

while (sscanf(hexPtr, "%02x", &result[i++])) {
    hexPtr += 2;
    if (hexPtr >= hexString + strlen(hexString)) break;
}

return result;
4
  • Could you clarify, shortly, on the few approaches you tried and in what type of context this code should fit? Commented May 18, 2010 at 12:23
  • 5
    (Maybe not the best but the shortest for sure;) possible duplicate of Code golf - hex to (raw) binary conversion Commented May 18, 2010 at 12:26
  • zaf, that is exactly what I wanted, sorry I didn't see that before. I guess this would in a way be a duplicate of that. Commented May 18, 2010 at 14:05
  • There's no need to cast &result[i++] to (unsigned int *) - it already has that type. Also you do not allocate enough space for result - you need to replace the final , 1) in the calloc call with sizeof *result. Commented May 18, 2010 at 22:41

6 Answers 6

2

Is the string always the same length?

If so:

char *buf = "55 AA 41 2A 00 94 55 AA BB BB 00 FF";
sscanf(buf, "%x %x %x [repeat as many times as necessary]", &a, &b, &c [etc]);

If not:

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

int main (int argc, char ** argv)
{
    char *buf = "55 AA 41 2A 00 94 55 AA BB BB 00 FF";
    char *p = buf;
    int i = 0, j;
    unsigned int *result = calloc(strlen(buf)/3 + 1 * sizeof(int), 1);

    if (result)
    {
        while (sscanf(p, "%02x", &result[i++]))
        {
             p += 3;
            if (p > buf + strlen(buf))
            {
             break;
            }
        }

        printf("%s\n", buf);

        for (j = 0; j < i; j++)
        {
            printf("%02X ", result[j]);
        }

        printf("\n");
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

The %02x conversion specifier requires a pointer to unsigned int, but you are passing it a pointer to unsigned char. This results in undefined behaviour (in practice, your answer will produce incorrect results on machines that aren't little-endian, and crash on machines with strict alignment requirements).
1

Did you try sscanf or scanf? This function processes hexadecimal values to and returns "raw data".

Comments

0
#define GETBITS(a) (a < 'A' ? a - '0' : toupper(a) - 'A' + 10)

char *cur;
char data;
for (cur = buffer; *cur; cur++) {
    data = GETBITS(cur[0]) << 4 + GETBITS(cur[1]);
    cur += 2;
    printf("%c", data);
}
printf("\n");

Comments

0
while(input[i]!='\0'){        
    *(temp++) = ((input[i]>='0' && input[i]<='9')?(input[i]-'0'):(input[i]-'a'+10))*16 +( (input[i+1]>='0' && input[i]<='9')?(input[i+1]-'0'):(input[i+1]-'a'+10));
         i+=2;
}

Comments

0
 /*
  * copyLeft (ButterC) All Right Changed :)
 */
 void _StackOverFlow(void *data) {

    unsigned char *ButterC = (unsigned char *) data;
    size_t ssize ,size = ssize = 0; 

    int i;

    for (i = 0; ButterC[i] != 0; i++)
    {
            if (ButterC[i] != 32)
                    size++;
    }

    unsigned int *resu = (unsigned int *) malloc((size / 2) + 1);


    while (*ButterC != 0 && resu != NULL && ssize < size) 
    {
            if (*ButterC == 32) 
                    ButterC++;
            else {
                    sscanf(ButterC,"%02x",&resu[ssize++]); ButterC += 2;
            }
    }
    // TEST RESULTE TO => (resu) 
    for (i = 0; i < ssize; i++)
    {
            printf("%02X ",resu[i] & 0xff);
    }

    puts(""); // NEWLINE  
}

int _start() {

    char data[] = "FF 00FF           01";
    _StackOverFlow(data);

    
    _exit(0);
}

Comments

0

I had a similar problem. I passed a "hex"-argument from python to a c-binary, i.e. 568AD6E4338BD93479C210105CD4198B, like:

subprocess.getoutput("binary.exe 568AD6E4338BD93479C210105CD4198B")

In my binary I wanted the passed argument to be stored in a uint8_t hexarray[16], but instead of char value '5' (raw hex 0x35), I needed actual raw hex value 0x5... and 32 chars make up a 16 sized uint8_t array, thus bit shifting etc..

for (i=0;i<16;i++) {
    if (argv[1][i*2]>0x40)
        hexarray[i] = ((argv[1][i*2] - 0x37) << 4);
    else 
        hexarray[i] = ((argv[1][i*2] - 0x30) << 4);
    if (argv[1][i*2+1]>0x40)
        hexarray[i] = hexarray[i] + (argv[1][i*2+1] - 0x37);
    else 
        hexarray[i] = hexarray[i] + (argv[1][i*2+1] - 0x30);

This would only work for hexstrings with upper chars.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.