views:

212

answers:

4

Hi - first post here :)

I've got a code like this in C:

unsigned char const data[ ] = {0x0a, 0x1d, 0xf0, 0x07};

I need to extract it such that the final value is:

0xa1df7

I have only been able to extract and get it working if the hex values that have at least 1 zero:

unsigned char const data[ ] = {0x0a, 0xd0, 0xf0, 0x07};

using the code below:

for(int i = 0; i < SIZE; ++i)
{
    tmp = data[i];
    if ( (data[i] <= 0x0F) &&  (((data[i] & 0x0F) == 0) || (data[i] & 0xF0) == 0)) // one of the hex is zero
    {
        tmp = ((tmp << 4) >> 4) << N[i];
        std::cout << "foo: " << std::hex << tmp << ":" << std::endl;    

    }
    else if ((data[i] >= 0x0F) &&  (((data[i] & 0x0F) == 0) || (data[i] & 0xF0) == 0) )
    {
        tmp = (tmp >> 4) << N[i];
        std::cout << "bar: " << std::hex << tmp << ":" << std::endl;

    }
    else
    {
        std::cout << "result: " << std::hex << result << ":" << std::endl;
        std::cout << "tmp << 8: " << std::hex << (tmp << 8)<< ":" << std::endl;
        result = result | (tmp << 8);
        std::cout << "result |= (tmp << 8): " << std::hex << result << ":" << std::endl;
    }

    result |= tmp;
    std::cout << "boo: " << std::hex << result << ":" << std::endl;
}

It seems the last else {...} block is troublesome for me. Any ideas? Thanks!

A: 

You'd better convert it all to a hex string first ("0a1df007") and then delete all zeroes :)

zed_0xff
+1 the easiest way
Iulian Şerbănoiu
not the easiest...since you'll have to convert the hexstring back to an integer. It seems like an overly complicated way of doing things
Toad
+5  A: 
#include <stdio.h>
#include <stdlib.h>

unsigned char const data[ ] = {0x0a, 0x1d, 0xf0, 0x07};

int main(int argc, char*argv[]){
    int i,r = 0;
    for(i=0; i<sizeof(data); i++){
        if(data[i] & 0xf0) r = (r<<4) + (data[i]>>4);
        if(data[i] & 0x0f) r = (r<<4) + (data[i]&0x0f);
    }
    printf("%x\n",r);
    return 0;
}

outputs "a1df7"

zed_0xff
Thanks zed_0xff! :)
Rjff
always great if 30 lines+ of code can be reduced to just a few ;^)
Toad
A: 
 unsigned char const data[ ] = {0x0a, 0x1d, 0xf0, 0x07};

 unsigned int value=0;
 for(int i=0; i<4; i++)
 {
     int nibble = (data[i] & 0xf0) >> 4;
     if(nibble > 0)
     {
          value<<=4;
          value += nibble;
     }
     nibble = data[i] & 0x0f;
     if(nibble > 0)
     {
          value<<=4;
          value += nibble;
     }
 }
Toad
A: 
unsigned char const data[ ] = {0x0a, 0x1d, 0xf0, 0x07};

Uhm, but that looks like a plain network byte order.

For 32bit int, do something like:

unsigned char *p = (unsigned char *)data;
int val = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];

And similarly for 64bit values.

P.S. Be careful about sign. In some cases explicit conversion to a signed type is required to force sign bit extension.

Dummy00001
That's not right. The required output is 'a1df7'. Thanks however.
Rjff
explain to me how 0x000a1df7 is different from 0xa1df7? or you need string? - `printf("%x\n", val)` - as %x strips leading zeros by default.
Dummy00001