Jak przekonwertować tablicę bajtów na ciąg szesnastkowy w C?

89

Mam:

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

Chcę przekonwertować tablicę bajtów na ciąg, tak że mogę wydrukować ciąg przy użyciu printf:

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

i otrzymaj (dwukropki nie są konieczne):

"00:01:0A:0B"

Każda pomoc byłaby bardzo mile widziana.

Steve Walsh
źródło
buf[i]musi być rzucony unsigned char, bo przepełni się, jeśli buf[i] > 127to jest:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);
jaka zimna

Odpowiedzi:

93
printf("%02X:%02X:%02X:%02X", buf[0], buf[1], buf[2], buf[3]);

aby uzyskać bardziej ogólny sposób:

int i;
for (i = 0; i < x; i++)
{
    if (i > 0) printf(":");
    printf("%02X", buf[i]);
}
printf("\n");

aby połączyć w ciąg, jest kilka sposobów, aby to zrobić ... prawdopodobnie trzymałbym wskaźnik na końcu ciągu i używałbym sprintf. powinieneś również śledzić rozmiar tablicy, aby upewnić się, że nie jest większy niż przydzielone miejsce:

int i;
char* buf2 = stringbuf;
char* endofbuf = stringbuf + sizeof(stringbuf);
for (i = 0; i < x; i++)
{
    /* i use 5 here since we are going to add at most 
       3 chars, need a space for the end '\n' and need
       a null terminator */
    if (buf2 + 5 < endofbuf)
    {
        if (i > 0)
        {
            buf2 += sprintf(buf2, ":");
        }
        buf2 += sprintf(buf2, "%02X", buf[i]);
    }
}
buf2 += sprintf(buf2, "\n");
Mark Synowiec
źródło
Dziękuję Mark - mój problem jest nieco bardziej skomplikowany. Właściwie mam bufor o długości X bajtów. Miałem nadzieję, że znajdę ogólny sposób zrobienia tego dla X bajtów i otrzymam w rezultacie łańcuch.
Steve Walsh
Właśnie zaktualizowano, aby dodać kod obsługujący dowolną liczbę bajtów ... zakładając, że x jest długością.
Mark Synowiec
Jeszcze raz dziękuję Mark, ale najtrudniejsze było dla mnie wydrukowanie tego na łańcuchu.
Steve Walsh
5
printf("%02X", (unsigned char)buf[i]);powinien być używany, ponieważ oryginał spowoduje przepełnienie dla znaków bez znaku
easytiger
3
Dlaczego nie printf("%02hhX", buf[i])?
Hintron
32

Aby uzyskać kompletność, możesz to również łatwo zrobić bez wywoływania żadnej ciężkiej funkcji bibliotecznej (bez snprintf, bez strcat, nawet memcpy). Może być przydatne, powiedzmy, jeśli programujesz jakiś mikrokontroler lub jądro systemu operacyjnego, w którym biblioteka libc nie jest dostępna.

Nie ma nic bardziej wyszukanego, co można znaleźć w pobliżu podobnego kodu, jeśli wyszukasz go w Google. Naprawdę nie jest to dużo bardziej skomplikowane niż wywołanie snprintf i znacznie szybsze.

#include <stdio.h>

int main(){
    unsigned char buf[] = {0, 1, 10, 11};
    /* target buffer should be large enough */
    char str[12];

    unsigned char * pin = buf;
    const char * hex = "0123456789ABCDEF";
    char * pout = str;
    int i = 0;
    for(; i < sizeof(buf)-1; ++i){
        *pout++ = hex[(*pin>>4)&0xF];
        *pout++ = hex[(*pin++)&0xF];
        *pout++ = ':';
    }
    *pout++ = hex[(*pin>>4)&0xF];
    *pout++ = hex[(*pin)&0xF];
    *pout = 0;

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

Oto kolejna, nieco krótsza wersja. Po prostu unika pośredniej zmiennej indeksu i oraz powielania kodu ostatniej sprawy (ale znak kończący jest zapisywany dwa razy).

#include <stdio.h>
int main(){
    unsigned char buf[] = {0, 1, 10, 11};
    /* target buffer should be large enough */
    char str[12];

    unsigned char * pin = buf;
    const char * hex = "0123456789ABCDEF";
    char * pout = str;
    for(; pin < buf+sizeof(buf); pout+=3, pin++){
        pout[0] = hex[(*pin>>4) & 0xF];
        pout[1] = hex[ *pin     & 0xF];
        pout[2] = ':';
    }
    pout[-1] = 0;

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

Poniżej znajduje się kolejna wersja, aby odpowiedzieć na komentarz mówiący, że użyłem "sztuczki", aby poznać rozmiar bufora wejściowego. Właściwie to nie jest sztuczka, ale niezbędna wiedza wejściowa (musisz znać rozmiar danych, które konwertujesz). Wyjaśniłem to, wyodrębniając kod konwersji do oddzielnej funkcji. Dodałem również kod kontroli granic dla bufora docelowego, co nie jest konieczne, jeśli wiemy, co robimy.

#include <stdio.h>

void tohex(unsigned char * in, size_t insz, char * out, size_t outsz)
{
    unsigned char * pin = in;
    const char * hex = "0123456789ABCDEF";
    char * pout = out;
    for(; pin < in+insz; pout +=3, pin++){
        pout[0] = hex[(*pin>>4) & 0xF];
        pout[1] = hex[ *pin     & 0xF];
        pout[2] = ':';
        if (pout + 3 - out > outsz){
            /* Better to truncate output string than overflow buffer */
            /* it would be still better to either return a status */
            /* or ensure the target buffer is large enough and it never happen */
            break;
        }
    }
    pout[-1] = 0;
}

int main(){
    enum {insz = 4, outsz = 3*insz};
    unsigned char buf[] = {0, 1, 10, 11};
    char str[outsz];
    tohex(buf, insz, str, outsz);
    printf("%s\n", str);
}
kriss
źródło
1
To nie jest sztuczka, tylko stała. W kontekście pytania jest jasne, że długość źródła, które chcemy przekonwertować na szesnastkowy, jest dobrze znana (mogłem wstawić trochę zakodowane 4 zamiast sizeof). W ogólnym przypadku funkcja powinna zostać wywołana na jakimś wejściu o znanej długości, a bufor docelowy ma dostępne 3 razy + 1 bajt. Musi to zapewnić dzwoniący, nie ma powodu, aby funkcja konwersji wykonywała to zadanie. Wywołanie strlen () może w niektórych przypadkach być sposobem na znalezienie rozmiaru źródła, ale nie zawsze. Co się stanie, jeśli liczba do przekonwertowania na szesnastkową zawiera zera?
kriss
Zainspirowany twoją funkcją napisałem wersję, która również zwraca liczbę bajtów zapisanych do bufora wyjściowego, podobnie jak snprintf itp. Gist.github.com/cellularmitosis/0d8c0abf7f8aa6a2dff3
Jason Pepas
Myślę, że powinieneś automatycznie ustawić odpowiedni rozmiar bufora wyjściowego za pomocą char str [sizeof (buf) * 3 + 1];
Cecil Ward
Chroniłoby cię również dużo więcej const. Np. „Const unsigned char const * p”, abyś mógł się upewnić, że bufory wejściowe nie są zapisywane. Jeden sprawia, że ​​adres (lub „wskaźnik”) jest stały lub zmienny, a drugi sprawia, że ​​pamięć pod tym adresem jest tylko do odczytu lub nie. Często powstrzymuje cię przed pomieszaniem wskazówek. Pomogłoby również posiadanie znaczących nazw, które dokumentują, które bufory i wskaźniki są dla wejścia i wyjścia.
Cecil Ward
@Cecil War: chyba, że ​​mój kod jest fałszywy, użycie const nie zapewni zbyt wiele, z wyjątkiem pomieszania wskaźników lub użycia tego samego wskaźnika do wejścia i wyjścia (ok, nadal możliwe). Ale pomoże też kompilatorowi zoptymalizować kod. Jeszcze lepiej byłoby użyć również słowa kluczowego restrykcyjnego (szkoda C99 nie C ++, ale często istnieje jako rozszerzenie kompilatora). Czego oczekujesz bardziej znaczącego niż wywołanie bufora wejściowego ini bufora wyjściowego out? Mógłbym również zdecydować się na użycie łańcucha i zwrócenie kopii zamiast dostarczania bufora wyjściowego, w nowoczesnych optymalizatorach C ++ są wystarczająco dobre, aby nie przejmować się zbytnio.
kriss
15

Oto metoda, która jest o wiele szybsza:

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

unsigned char *     bin_to_strhex(const unsigned char *bin, unsigned int binsz,
                                  unsigned char **result)
{
  unsigned char     hex_str[]= "0123456789abcdef";
  unsigned int      i;

  if (!(*result = (unsigned char *)malloc(binsz * 2 + 1)))
    return (NULL);

  (*result)[binsz * 2] = 0;

  if (!binsz)
    return (NULL);

  for (i = 0; i < binsz; i++)
    {
      (*result)[i * 2 + 0] = hex_str[(bin[i] >> 4) & 0x0F];
      (*result)[i * 2 + 1] = hex_str[(bin[i]     ) & 0x0F];
    }
  return (*result);
}

int                 main()
{
  //the calling
  unsigned char     buf[] = {0,1,10,11};
  unsigned char *   result;

  printf("result : %s\n", bin_to_strhex((unsigned char *)buf, sizeof(buf), &result));
  free(result);

  return 0
}
Yannuth
źródło
3
Ten kod zawiera błąd, który objawia się tylko na dziwnych, niedrukowalnych danych wejściowych (nie miałem czasu, aby dokładnie zagłębić się w to, co dzieje się matematycznie). Spróbuj zakodować liczbę binarną lub szesnastkową, ca9e3c972f1c5db40c0b4a66ab5bc1a20ca4457bdbe5e0f8925896d5ed37d726a wyjdziesz ÌaÌe3cÌ72f1c5dÌ40c0b4a66Ìb5bÌ1Ì20cÌ4457bÌbÌ5Ì0Ì8Ì258Ì6Ì5Ìd37Ì726. Aby to naprawić, bit wewnątrz hex_strpierwszej linii pętli for musi zostać zmieniony na taki, (input[i] >> 4) & 0x0Fjak w odpowiedzi @ kriss. Wtedy działa dobrze.
niemiro
Błąd - nie sprawdza błędu malloc ().
Cecil Ward
Zawsze lepiej jest używać znaków bez znaku absolutnie wszędzie, ponieważ nikt nie chce ryzykować podpisania znaków (szalona cecha sprzętowa DEC PDP11), a w ten sposób nie ryzykujesz, że podpisane porównania pójdą źle lub podpisane poprawne przesunięcia zniekształcają wartości. W tym przypadku, aby być uczciwym, kod defensywnie wykonuje & 0x0F wszędzie, co cię tutaj chroni.
Cecil Ward
Parametr wejściowy bin powinien mieć wartość const unsigned char const * bin, aby zadeklarować pamięć jako tylko do odczytu na potrzeby tej procedury.
Cecil Ward
1
Zintegrowałem propozycje Cecila Warda, dzięki za informację zwrotną
Yannuth
14

Podobne odpowiedzi już istnieją powyżej, dodałem tę, aby wyjaśnić, jak dokładnie działa następujący wiersz kodu:

ptr += sprintf(ptr, "%02X", buf[i])

Jest cicho trudne i niełatwe do zrozumienia, wyjaśnienie zamieszczam w komentarzach poniżej:

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

/* Allocate twice the number of bytes in the "buf" array because each byte would
 * be converted to two hex characters, also add an extra space for the terminating
 * null byte.
 * [size] is the size of the buf array */
char output[(size * 2) + 1];

/* pointer to the first item (0 index) of the output array */
char *ptr = &output[0];

int i;

for (i = 0; i < size; i++) {
    /* "sprintf" converts each byte in the "buf" array into a 2 hex string
     * characters appended with a null byte, for example 10 => "0A\0".
     *
     * This string would then be added to the output array starting from the
     * position pointed at by "ptr". For example if "ptr" is pointing at the 0
     * index then "0A\0" would be written as output[0] = '0', output[1] = 'A' and
     * output[2] = '\0'.
     *
     * "sprintf" returns the number of chars in its output excluding the null
     * byte, in our case this would be 2. So we move the "ptr" location two
     * steps ahead so that the next hex string would be written at the new
     * location, overriding the null byte from the previous hex string.
     *
     * We don't need to add a terminating null byte because it's been already 
     * added for us from the last hex string. */  
    ptr += sprintf(ptr, "%02X", buf[i]);
}

printf("%s\n", output);
razz
źródło
Genialna logika. Szukałem godziny na elegancką odpowiedź w języku innym niż C ++ na to wyzwanie!
Mark Terrill
6

Chciałem tylko dodać następujące, nawet jeśli jest to nieco nie na temat (nie standardowe C), ale często go szukam i natknąłem się na to pytanie wśród pierwszych wyników wyszukiwania. Funkcja drukowania jądra Linuksa printkzawiera również specyfikatory formatu do wyprowadzania zawartości tablicy / pamięci „bezpośrednio” przez specyfikator formatu pojedynczego:

https://www.kernel.org/doc/Documentation/printk-formats.txt

Raw buffer as a hex string:
    %*ph    00 01 02  ...  3f
    %*phC   00:01:02: ... :3f
    %*phD   00-01-02- ... -3f
    %*phN   000102 ... 3f

    For printing a small buffers (up to 64 bytes long) as a hex string with
    certain separator. For the larger buffers consider to use
    print_hex_dump(). 

... jednak wydaje się, że te specyfikatory formatu nie istnieją dla standardowej przestrzeni użytkownika (s)printf.

sdaau
źródło
5

Rozwiązanie

Funkcja btoxkonwertuje dowolne dane *bbdo niezakończony ciąg *xpz ncyfr szesnastkowych:

void btox(char *xp, const char *bb, int n) 
{
    const char xx[]= "0123456789ABCDEF";
    while (--n >= 0) xp[n] = xx[(bb[n>>1] >> ((1 - (n&1)) << 2)) & 0xF];
}

Przykład

#include <stdio.h>

typedef unsigned char uint8;

void main(void) 
{
    uint8 buf[] = {0, 1, 10, 11};
    int n = sizeof buf << 1;
    char hexstr[n + 1];

    btox(hexstr, buf, n);
    hexstr[n] = 0; /* Terminate! */
    printf("%s\n", hexstr);
}

Wynik: 00010A0B .

Na żywo: Tio.run .

7vujy0f0hy
źródło
1

Oto jeden ze sposobów wykonania konwersji:

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

#define l_word 15
#define u_word 240

char *hex_str[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};

main(int argc,char *argv[]) {


     char *str = malloc(50);
     char *tmp;
     char *tmp2;

     int i=0;


     while( i < (argc-1)) {
          tmp = hex_str[*(argv[i]) & l_word];
          tmp2 = hex_str[*(argv[i]) & u_word];

          if(i == 0) { memcpy(str,tmp2,1); strcat(str,tmp);}
          else { strcat(str,tmp2); strcat(str,tmp);}
          i++;
    }

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

}
rajaganesh
źródło
1

Nieznacznie zmodyfikowana wersja Yannith. Po prostu lubię mieć to jako wartość zwracaną

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

Michaił Baynov
źródło
1

Ta funkcja jest odpowiednia, gdy użytkownik / dzwoniący chce, aby ciąg szesnastkowy został umieszczony w tablicy / buforze znaków. Z ciągiem szesnastkowym w buforze znaków, użytkownik / dzwoniący może użyć własnego makra / funkcji do wyświetlenia lub zarejestrowania go w dowolnym miejscu (np. Do pliku). Ta funkcja pozwala również wywołującemu kontrolować liczbę (szesnastkowych) bajtów, które mają być umieszczone w każdej linii.

/**
 * @fn 
 * get_hex
 *
 * @brief 
 * Converts a char into bunary string 
 *
 * @param[in]   
 *     buf Value to be converted to hex string
 * @param[in]   
 *     buf_len Length of the buffer
 * @param[in]   
 *     hex_ Pointer to space to put Hex string into
 * @param[in]   
 *     hex_len Length of the hex string space
 * @param[in]   
 *     num_col Number of columns in display hex string
 * @param[out]   
 *     hex_ Contains the hex string
 * @return  void
 */
static inline void
get_hex(char *buf, int buf_len, char* hex_, int hex_len, int num_col)
{
    int i;
#define ONE_BYTE_HEX_STRING_SIZE   3
  unsigned int byte_no = 0;

  if (buf_len <= 0) {
      if (hex_len > 0) {
        hex_[0] = '\0';
      }
      return;
  }

  if(hex_len < ONE_BYTE_HEX_STRING_SIZE + 1)
  {
      return;
  }

  do {
         for (i = 0; ((i < num_col) && (buf_len > 0) && (hex_len > 0)); ++i )
         {
            snprintf(hex_, hex_len, "%02X ", buf[byte_no++] & 0xff);
            hex_ += ONE_BYTE_HEX_STRING_SIZE;
            hex_len -=ONE_BYTE_HEX_STRING_SIZE;
            buf_len--;
         }
         if (buf_len > 1)
         {
             snprintf(hex_, hex_len, "\n");
             hex_ += 1;
         }
  } while ((buf_len) > 0 && (hex_len > 0));

}

Przykład: kod

#define DATA_HEX_STR_LEN 5000
    char      data_hex_str[DATA_HEX_STR_LEN];

    get_hex(pkt, pkt_len, data_hex_str, DATA_HEX_STR_LEN, 16);
    //      ^^^^^^^^^^^^                                  ^^
    //      Input byte array                              Number of (hex) byte
    //      to be converted to hex string                 columns in hex string

    printf("pkt:\n%s",data_hex_str) 

WYNIK

pkt:
BB 31 32 00 00 00 00 00 FF FF FF FF FF FF DE E5 
A8 E2 8E C1 08 06 00 01 08 00 06 04 00 01 DE E5 
A8 E2 8E C1 67 1E 5A 02 00 00 00 00 00 00 67 1E 
5A 01 
Sandesh Kumar Sodhi
źródło
0

Nie ma na to żadnego prymitywu w C. Prawdopodobnie malloc (lub może przydzieliłbym) wystarczająco długi bufor i pętlę na wejściu. Widziałem również, że jest to zrobione z dynamiczną biblioteką ciągów z semantyką (ale nie składnią!) Podobną do C ++ ostringstream, która jest prawdopodobnie bardziej ogólnym rozwiązaniem, ale może nie być warta dodatkowej złożoności tylko dla pojedynczego przypadku.

crazyscot
źródło
0

Jeśli chcesz przechowywać wartości szesnastkowe w char *ciągu, możesz użyćsnprintf . Musisz przydzielić miejsce na wszystkie drukowane znaki, w tym na początkowe zera i dwukropek.

Rozwinięcie odpowiedzi Marka:

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

Więc teraz str_bufbędzie zawierał ciąg szesnastkowy.

Panie Shickadance
źródło
to nadpisuje pierwsze 2 znaki w kółko… prawda?
xordon
0

Rozwiązanie ZincX dostosowane do ograniczników okrężnicy:

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);
}
Gnubie
źródło
0

Dodam tutaj wersję C ++ dla każdego, kto jest zainteresowany.

#include <iostream>
#include <iomanip>
inline void print_bytes(char const * buffer, std::size_t count, std::size_t bytes_per_line, std::ostream & out) {
    std::ios::fmtflags flags(out.flags()); // Save flags before manipulation.
    out << std::hex << std::setfill('0');
    out.setf(std::ios::uppercase);
    for (std::size_t i = 0; i != count; ++i) {
        auto current_byte_number = static_cast<unsigned int>(static_cast<unsigned char>(buffer[i]));
        out << std::setw(2) << current_byte_number;
        bool is_end_of_line = (bytes_per_line != 0) && ((i + 1 == count) || ((i + 1) % bytes_per_line == 0));
        out << (is_end_of_line ? '\n' : ' ');
    }
    out.flush();
    out.flags(flags); // Restore original flags.
}

Wypisze zrzut heksowy bufferdługości countdo std::ostream out(możesz ustawić go jako domyślny std::cout). Każdy wiersz będzie zawierał bytes_per_linebajty, każdy bajt jest reprezentowany za pomocą dwucyfrowych liter szesnastkowych. Pomiędzy bajtami będzie spacja. A na końcu linii lub na końcu bufora wypisze znak nowej linii. Jeśli bytes_per_linejest ustawiona na 0, nie będzie drukować nowej linii. Spróbuj sam.

WiSaGaN
źródło
0

Dla prostego użycia stworzyłem funkcję, która koduje ciąg wejściowy (dane binarne):

/* 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;
}

Stosowanie:

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;
mbuster
źródło
0

Oparte na odpowiedzi Yannutha, ale uproszczone.

Tutaj dest[]zakłada się , że długość wynosi dwa razy więcej len, a jej alokacją zarządza wywołujący.

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];
    }
}
konsolebox
źródło
0

Wiem, że to pytanie ma już odpowiedź, ale myślę, że moje rozwiązanie może komuś pomóc.

Tak więc w moim przypadku miałem tablicę bajtów reprezentującą klucz i musiałem przekonwertować tę tablicę bajtów na tablicę znaków szesnastkowych, aby wydrukować ją w jednym wierszu. Wyodrębniłem mój kod do funkcji takiej jak ta:

char const * keyToStr(uint8_t const *key)
{
    uint8_t offset = 0;
    static char keyStr[2 * KEY_SIZE + 1];

    for (size_t i = 0; i < KEY_SIZE; i++)
    {
        offset += sprintf(keyStr + offset, "%02X", key[i]);
    }
    sprintf(keyStr + offset, "%c", '\0');

    return keyStr;
}

Teraz mogę użyć mojej funkcji w ten sposób:

Serial.print("Public key: ");
Serial.println(keyToStr(m_publicKey));

Serialobiekt jest częścią biblioteki Arduino i m_publicKeyjest członkiem mojej klasy z następującą deklaracją uint8_t m_publicKey[32].

Orzechówka
źródło
0

Możesz rozwiązać za pomocą snprintf i malloc.

char c_buff[50];

u8_number_val[] = { 0xbb, 0xcc, 0xdd, 0x0f, 0xef, 0x0f, 0x0e, 0x0d, 0x0c };

char *s_temp = malloc(u8_size * 2 + 1);

for (uint8_t i = 0; i < u8_size; i++)
{
    snprintf(s_temp  + i * 2, 3, "%02x", u8_number_val[i]);
}

snprintf(c_buff, strlen(s_temp)+1, "%s", s_temp );

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

free(s);

OUT: bbccdd0fef0f0e0d0c

barbaros
źródło
-2

Jakie skomplikowane rozwiązania!
Malloc, sprinty i rzuty ojej. (Cytat z OZ)
i nigdzie ani jednego rema. Boże,

co powiesz na coś takiego?

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

}
Stephen George
źródło
OK, teraz masz dwie cyfry szesnastkowe. Pozostaje dodać separatory i zadbać o pozostałe bajty do konwersji. Może z pętlą? Zrób z tego funkcję, a otrzymasz coś podobnego do mojego (ale raczej rozwlekłego i trudnego do odczytania). Może powinieneś przynajmniej skończyć pracę, zanim zawołasz nazwiska na innych plakatach?
kriss
1
I słowo o komentarzach w kodzie źródłowym (nie REM, to BASIC słowo kluczowe dla komentarzy, proszę tego unikać): komentarze mówiące po angielsku, co robi kod, to bardzo, bardzo zła praktyka! Tak, programiści powinni wiedzieć, co oznaczają operatory modulo (podaj resztę) i ten podział liczy, ile razy liczba pojawia się w innej ... i to printf wypisuje wynik. O mój!
kriss