Domanda

I tried to imitate a struct with a unsigned char array or pointer, but I am not able to obtain the same hex values.

.input is correct with print(). I am trying to get the same effect from stringBytes_Data or data_hexStrFormatted with print().

Can anyone advise?

Given

struct _vector {
char *input;
unsigned char len;
};


static struct _vector tv2 = {
   .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
            "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
            "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
            "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
            "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
            "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
            "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
            "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
   .len = 64,
};

And function to view the data:

static void print(char *intro_message, unsigned char *text_addr,
                    unsigned int size) {
unsigned int   i;

for (i = 0;  i < size;  i++) {
    printf("%2x ", text_addr[i]);
    if ((i & 0xf) == 0xf)
        printf("\n");
}
printf("\n");
}

How may I get the same effect with:

char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";                

I tried, but the result is wrong :

unsigned char* data_hexStrFormatted;

int lengthOfStr = strlen(stringBytes_Data);
int charCounterForNewStr = 0;       
int formattedLength = (2*lengthOfStr)+1;

data_hexStrFormatted = (unsigned char*) malloc((formattedLength)*sizeof(unsigned char)); // x2 as we add \x to XX, and 1 for NULL end char


for(i=0; i<lengthOfStr; i=i+2) { 
      // prepend \x
         data_hexStrFormatted[charCounterForNewStr++] = '\\';
         data_hexStrFormatted[charCounterForNewStr++] = 'x';

      data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i]; 
      data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i+1];
} 
data_hexStrFormatted[formattedLength-1] = '\0';

printf("%s\n", data_hexStrFormatted);
printf("%d byte length \n", strlen(data_hexStrFormatted)/4);

 print("data_hexStrFormatted",
                    (unsigned char *)
                    data_hexStrFormatted,
                    (formattedLength)/4); 
È stato utile?

Soluzione

You seem to be asking:

  • Given a string containing pairs of hex digits, convert the hex digits to byte values?

If so, then code similar to the following can be used:

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

This function works correctly for valid hex digits; it will produce nonsense for invalid inputs. If you decide you need to detect erroneous input, you'll need to improve it. There are other ways to write this function (lots of them, in fact). One that can be effective is an array of 256 bytes statically initialized with the correct values, so you simply write return hex_array[c];.

char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";

size_t len = strlen(stringBytes_Data);
char buffer[len / 2];

assert(len % 2 == 0);

for (size_t i = 0; i < len; i += 2)
    buffer[i / 2] = hexit(stringBytes_Data[i]) << 4 | hexit(stringBytes_Data[i+1]);

printf("%.*s\n", (int)len/2, buffer);

This code sets the array buffer to contain the converted code. It won't work correctly if there's an odd number of characters in the array (that's what the assertion states).


Working code - #2

Using the print() function from the question with the info_message argument removed since it is unused:

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

struct Vector
{
    char *input;
    unsigned char len;
};

static struct Vector tv2 =
{
    .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
             "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
             "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
             "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
             "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
             "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
             "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
             "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
    .len = 64,
};

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

static void print(unsigned char *text_addr, unsigned int size)
{
    unsigned int i;

    for (i = 0; i < size; i++)
    {
        printf("%2x ", text_addr[i]);
        if ((i & 0xf) == 0xf)
            printf("\n");
    }
    printf("\n");
}

static void print2(const char *tag, const unsigned char *data, size_t size)
{
    printf("%s:\n", tag);
    for (size_t i = 0; i < size; i++)
    {
        printf("%2x ", data[i]);
        if ((i & 0x0F) == 0x0F)
            printf("\n");
    }
    printf("\n");
}

static void print_text(const char *tag, const char *data, size_t datalen)
{
    char buffer[datalen / 2];

    assert(datalen % 2 == 0);

    for (size_t i = 0; i < datalen; i += 2)
        buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);

    //printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
    assert(memcmp(buffer, tv2.input, tv2.len) == 0);
    print((unsigned char *)buffer, datalen / 2);
    print2(tag, (unsigned char *)buffer, datalen / 2);
}

int main(void)
{
    char *stringBytes_Data =
        "6bc1bee22e409f96e93d7e117393172a"
        "ae2d8a571e03ac9c9eb76fac45af8e51"
        "30c81c46a35ce411e5fbc1191a0a52ef"
        "f69f2445df4f9b17ad2b417be66c3710"
    ;

    print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
    return 0;
}

Sample output:

6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

Working code - #1

Redone — previous versions had various 'off by a factor of two' errors which were partially concealed by the system zeroing a buffer.

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

struct Vector
{
    char *input;
    unsigned char len;
};

static struct Vector tv2 =
{
    .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
             "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
             "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
             "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
             "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
             "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
             "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
             "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
    .len = 64,
};

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

static void print(const char *tag, const unsigned char *data, size_t size)
{
    printf("%s:\n", tag);
    for (size_t i = 0; i < size; i++)
    {
        printf("%2x ", data[i]);
        if ((i & 0x0F) == 0x0F)
            printf("\n");
    }
    printf("\n");
}

static void print_text(const char *tag, const char *data, size_t datalen)
{
    char buffer[datalen / 2];

    assert(datalen % 2 == 0);

    for (size_t i = 0; i < datalen; i += 2)
        buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);

    printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
    assert(memcmp(buffer, tv2.input, tv2.len) == 0);
    print(tag, (unsigned char *)buffer, datalen / 2);
}

int main(void)
{
    char *stringBytes_Data =
        "6bc1bee22e409f96e93d7e117393172a"
        "ae2d8a571e03ac9c9eb76fac45af8e51"
        "30c81c46a35ce411e5fbc1191a0a52ef"
        "f69f2445df4f9b17ad2b417be66c3710"
    ;

    print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
    return 0;
}

Raw output on a UTF-8 terminal (it isn't valid UTF-8 data, hence the question marks):

buffer: [[k???.@???=~s?*?-?W????o?E??Q0?F?\????
R???$E?O??+A{?l7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

Raw output converted into UTF-8 as if it was ISO 8859-15 (or 8859-1):

buffer: [[kÁŸâ.@é=~s*®-W¬·o¬E¯Q0ÈF£\äåûÁ
Rïö$EßO­+A{æl7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

The data doesn't seem to have any particular meaning, but beauty is in the eye of the beholder.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top