Как преобразовать байтовый массив в шестнадцатеричную строку в C? - PullRequest
74 голосов
/ 15 июня 2011

У меня есть:

uint8 buf[] = {0, 1, 10, 11};

Я хочу преобразовать массив байтов в строку так, чтобы я мог напечатать строку, используя printf:

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

и получить (двоеточиене нужно):

"00:01:0A:0B"

Любая помощь будет принята с благодарностью.

Ответы [ 17 ]

0 голосов
/ 16 августа 2017

Основано на ответе Яннута , но упрощено.

Здесь длина dest[] подразумевается вдвое больше len, и ее распределение управляется вызывающей стороной.*

void create_hex_string_implied(const unsigned char *src, size_t len, unsigned char *dest)
{
    static const unsigned char table[] = "0123456789abcdef";

    for (; len > 0; --len)
    {
        unsigned char c = *src++;
        *dest++ = table[c >> 4];
        *dest++ = table[c & 0x0f];
    }
}
0 голосов
/ 15 июня 2011

Если вы хотите сохранить шестнадцатеричные значения в строке char *, вы можете использовать snprintf.Вам нужно выделить место для всех напечатанных символов, включая начальные нули и двоеточие.

Расширение ответа Марка:

char str_buf* = malloc(3*X + 1);   // X is the number of bytes to be converted

int i;
for (i = 0; i < x; i++)
{
    if (i > 0) snprintf(str_buf, 1, ":");
    snprintf(str_buf, 2, "%02X", num_buf[i]);  // need 2 characters for a single hex value
}
snprintf(str_buf, 2, "\n\0"); // dont forget the NULL byte

Так что теперь str_buf будет содержать шестнадцатеричную строку.

0 голосов
/ 10 января 2016

Слегка модифицированная версия Yannith. Просто мне нравится иметь его в качестве возвращаемого значения

typedef struct {
   size_t len;
   uint8_t *bytes;
} vdata;

char* vdata_get_hex(const vdata data)
{
   char hex_str[]= "0123456789abcdef";

   char* out;
   out = (char *)malloc(data.len * 2 + 1);
   (out)[data.len * 2] = 0;
   
   if (!data.len) return NULL;
   
   for (size_t i = 0; i < data.len; i++) {
      (out)[i * 2 + 0] = hex_str[(data.bytes[i] >> 4) & 0x0F];
      (out)[i * 2 + 1] = hex_str[(data.bytes[i]     ) & 0x0F];
   }
   return out;
}
0 голосов
/ 28 ноября 2015

Для простоты использования я сделал функцию, которая кодирует входную строку (двоичные данные):

/* Encodes string to hexadecimal string reprsentation
    Allocates a new memory for supplied lpszOut that needs to be deleted after use
    Fills the supplied lpszOut with hexadecimal representation of the input
    */
void StringToHex(unsigned char *szInput, size_t size_szInput, char **lpszOut)
{
    unsigned char *pin = szInput;
    const char *hex = "0123456789ABCDEF";
    size_t outSize = size_szInput * 2 + 2;
    *lpszOut = new char[outSize];
    char *pout = *lpszOut;
    for (; pin < szInput + size_szInput; pout += 2, pin++)
    {
        pout[0] = hex[(*pin >> 4) & 0xF];
        pout[1] = hex[*pin & 0xF];
    }
    pout[0] = 0;
}

Использование:

unsigned char input[] = "This is a very long string that I want to encode";
char *szHexEncoded = NULL;
StringToHex(input, strlen((const char *)input), &szHexEncoded);

printf(szHexEncoded);

// The allocated memory needs to be deleted after usage
delete[] szHexEncoded;
0 голосов
/ 13 октября 2014

Какие сложные решения!
Маллок, и спринты, и слепки, о боже.(OZ цитата)
и ни одного бэра нигде.Черт возьми

Как насчет этого?

main()
{
    // the value
    int value = 16;

    // create a string array with a '\0' ending ie. 0,0,0
    char hex[]= {0,0,'\0'}; 
    char *hex_p=hex;

    //a working variable
    int TEMP_int=0;

    // get me how many 16s are in this code
    TEMP_int=value/16;

    // load the first character up with 
    // 48+0 gives you ascii 0, 55+10 gives you ascii A
    if (TEMP_int<10) {*hex_p=48+TEMP_int;}
        else {*hex_p=55+TEMP_int;}

    // move that pointer to the next (less significant byte)<BR>
    hex_p++;

    // get me the remainder after I have divied by 16
    TEMP_int=value%16;

    // 48+0 gives you ascii 0, 55+10 gives you ascii A
    if (TEMP_int<10) {*hex_p=48+TEMP_int;}
        else {*hex_p=55+TEMP_int;}

    // print the result
    printf("%i , 0x%s",value,hex);

}
0 голосов
/ 15 июня 2011

В Си нет примитива для этого. Я бы, вероятно, использовал malloc (или, возможно, alloca) достаточно длинный буфер и зацикливал ввод.Я также видел, что это было сделано с динамической библиотекой строк с семантикой (но не с синтаксисом!), Похожей на ostringstream в C ++, которая является более правдоподобным решением, но может не стоить дополнительной сложности только для одного случая.

0 голосов
/ 09 декабря 2011

Решение ZincX, адаптированное для включения разделителей двоеточия:

char buf[] = {0,1,10,11};
int i, size = sizeof(buf) / sizeof(char);
char *buf_str = (char*) malloc(3 * size), *buf_ptr = buf_str;
if (buf_str) {
  for (i = 0; i < size; i++)
    buf_ptr += sprintf(buf_ptr, i < size - 1 ? "%02X:" : "%02X\0", buf[i]);
  printf("%s\n", buf_str);
  free(buf_str);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...