Wie konvertiert man ein Byte-Array in eine hexadezimale Zeichenfolge in C?

88

Ich habe:

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

Ich möchte das Byte-Array in eine Zeichenfolge konvertieren, damit ich die Zeichenfolge mit printf drucken kann:

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

und bekommen (die Doppelpunkte sind nicht notwendig):

"00:01:0A:0B"

Jede Hilfe wäre sehr dankbar.

Steve Walsh
quelle
buf[i]muss gegossen werden unsigned char, oder es wird überlaufen, wenn buf[i] > 127das heißt:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);
whatacold

Antworten:

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

für einen allgemeineren Weg:

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

Um sich mit einer Zeichenfolge zu verketten, gibt es einige Möglichkeiten, wie Sie dies tun können ... Ich würde wahrscheinlich einen Zeiger auf das Ende der Zeichenfolge behalten und sprintf verwenden. Sie sollten auch die Größe des Arrays verfolgen, um sicherzustellen, dass es nicht größer als der zugewiesene Speicherplatz wird:

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
quelle
Danke Mark - mein Problem ist etwas komplizierter. Ich habe tatsächlich einen Puffer mit einer Länge von X Bytes. Ich hatte gehofft, einen generischen Weg zu finden, dies für X Bytes zu tun und als Ergebnis einen String zu haben.
Steve Walsh
Gerade aktualisiert, um Code für die Verarbeitung einer bestimmten Anzahl von Bytes hinzuzufügen ... vorausgesetzt, x ist die Länge.
Mark Synowiec
Nochmals vielen Dank Mark, aber das, was ich für dieses Problem am schwierigsten fand, ist, wie man dies auf eine Zeichenfolge druckt.
Steve Walsh
5
printf("%02X", (unsigned char)buf[i]);sollte verwendet werden, da das Original einen Überlauf für nicht signierte Zeichen verursacht
easytiger
3
Warum nicht printf("%02hhX", buf[i])?
Hintron
32

Zum Abschluss können Sie dies auch problemlos tun, ohne eine umfangreiche Bibliotheksfunktion aufzurufen (kein snprintf, kein strcat, nicht einmal memcpy). Dies kann beispielsweise nützlich sein, wenn Sie einen Mikrocontroller oder einen Betriebssystemkern programmieren, für den libc nicht verfügbar ist.

Nichts Besonderes, Sie können ähnlichen Code finden, wenn Sie danach googeln. Wirklich, es ist nicht viel komplizierter als snprintf aufzurufen und viel schneller.

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

Hier ist eine weitere etwas kürzere Version. Es wird lediglich die Zwischenindexvariable i und das Duplizieren des letzten Fallcodes vermieden (das abschließende Zeichen wird jedoch zweimal geschrieben).

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

Unten finden Sie eine weitere Version, um auf einen Kommentar zu antworten, der besagt, dass ich einen "Trick" verwendet habe, um die Größe des Eingabepuffers zu ermitteln. Eigentlich ist es kein Trick, sondern ein notwendiges Eingabewissen (Sie müssen die Größe der Daten kennen, die Sie konvertieren). Ich habe dies klarer gemacht, indem ich den Konvertierungscode in eine separate Funktion extrahiert habe. Ich habe auch einen Grenzprüfcode für den Zielpuffer hinzugefügt, der nicht wirklich notwendig ist, wenn wir wissen, was wir tun.

#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
quelle
1
Es ist kein Trick, nur eine Konstante. Im Zusammenhang mit der Frage ist klar, dass die Länge der Quelle, die wir in hexadezimal konvertieren möchten, bekannt ist (ich hätte einige hardcodierte 4 anstelle von sizeof setzen können). Im allgemeinen Fall sollte die Funktion bei einer Eingabe bekannter Länge aufgerufen werden, und dem Zielpuffer stehen 3 mal + 1 Byte zur Verfügung. Dies muss vom Aufrufer sichergestellt werden, es gibt keinen Grund für die Konvertierungsfunktion, diese Aufgabe auszuführen. Das Aufrufen von strlen () kann in einigen Fällen eine Möglichkeit sein, die Quellgröße zu ermitteln, jedoch nicht immer. Was ist, wenn die in Hex umzuwandelnde Zahl Nullen enthält?
Kriss
Inspiriert von Ihrer Funktion habe ich eine Version geschrieben, die auch die Anzahl der in den Ausgabepuffer geschriebenen Bytes zurückgibt, ähnlich wie snprintf usw. gist.github.com/cellularmitosis/0d8c0abf7f8aa6a2dff3
Jason Pepas
Ich denke, Sie sollten Ihren Ausgabepuffer automatisch mit char str [sizeof (buf) * 3 + 1] auf die richtige Größe einstellen.
Cecil Ward
Auch viel mehr Konstanten würden dich beschützen. ZB "const unsigned char const * p", damit Sie sicherstellen können, dass keine Eingabepuffer geschrieben werden. Einer macht die Adresse (oder den 'Zeiger') konstant oder variabel, und der andere macht den Speicher an dieser Adresse schreibgeschützt oder nicht. Hält Sie oft davon ab, die Zeiger durcheinander zu bringen. Außerdem würde es helfen, aussagekräftige Namen zu haben, die dokumentieren, welche Puffer und Zeiger für die Eingabe und Ausgabe bestimmt sind.
Cecil Ward
@ Cecil War: Wenn mein Code nicht falsch ist, schützt die Verwendung von const nicht viel, außer wenn Sie sagen, dass Zeiger verwechselt werden oder dass derselbe Zeiger für die Eingabe und Ausgabe verwendet wird (ok, immer noch möglich). Es wird dem Compiler aber auch helfen, den Code zu optimieren. Noch besser wäre es, auch das Schlüsselwort Restrict zu verwenden (schade, dass C99 nicht C ++ ist, sondern häufig als Compiler-Erweiterung vorhanden ist). Was möchten Sie mehr als den Aufruf von Eingabepuffer inund Ausgabepuffer out? Ich könnte mich auch dafür entscheiden, einen String zu verwenden und eine Kopie zurückzugeben, anstatt einen Ausgabepuffer bereitzustellen. In modernen C ++ - Optimierern sind sie gut genug, um sich nicht darum zu kümmern.
Kriss
15

Hier ist eine Methode, die viel schneller ist:

#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
quelle
3
Dieser Code enthält einen Fehler, der sich nur bei seltsamen, nicht druckbaren Eingaben manifestiert (ich hatte keine Zeit, mich genau mit den mathematischen Vorgängen zu befassen). Versuchen Sie, die Binärdatei von hexadezimal zu codieren, ca9e3c972f1c5db40c0b4a66ab5bc1a20ca4457bdbe5e0f8925896d5ed37d726und Sie werden aussteigen ÌaÌe3cÌ72f1c5dÌ40c0b4a66Ìb5bÌ1Ì20cÌ4457bÌbÌ5Ì0Ì8Ì258Ì6Ì5Ìd37Ì726. Um dies zu beheben, muss das Bit hex_strin der ersten Zeile der for-Schleife (input[i] >> 4) & 0x0Fwie in der Antwort von @ kriss geändert werden . Dann funktioniert es gut.
niemandiro
Fehler - prüft nicht auf den Fehler malloc ().
Cecil Ward
Es ist immer besser, vorzeichenloses Zeichen absolut überall zu verwenden, da niemand das Risiko von vorzeichenbehafteten Zeichen (eine verrückte DEC PDP11-Hardwarefunktion) haben möchte. Auf diese Weise laufen Sie nicht Gefahr, dass vorzeichenbehaftete Vergleiche schief gehen oder vorzeichenbehaftete Rechte die Werte beschädigen. In diesem Fall führt der Code, um fair zu sein, überall defensiv ein & 0x0F aus, was Sie hier schützt.
Cecil Ward
Der bin-Eingabeparameter sollte const unsigned char const * bin sein, um den Speicher für die Zwecke dieser Routine als schreibgeschützt zu deklarieren.
Cecil Ward
1
Ich habe die Vorschläge von Cecil Ward integriert, danke für das Feedback
Yannuth
13

Ähnliche Antworten gibt es bereits oben. Ich habe diese hinzugefügt, um zu erklären, wie die folgende Codezeile genau funktioniert:

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

Es ist ziemlich knifflig und nicht leicht zu verstehen. Ich habe die Erklärung in den Kommentaren unten angegeben:

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
quelle
Geniale Logik. Ich suchte eine Stunde nach einer eleganten Nicht-C ++ - String-Antwort auf diese Herausforderung!
Mark Terrill
5

Ich wollte nur Folgendes hinzufügen, auch wenn es etwas vom Thema abweicht (nicht Standard C), aber ich suche oft danach und stoße bei den ersten Suchtreffern auf diese Frage. Die Linux-Kernel-Druckfunktion printkverfügt auch über Formatspezifizierer für die Ausgabe von Array- / Speicherinhalten "direkt" über einen einzelnen Formatspezifizierer:

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(). 

... diese Formatspezifizierer scheinen jedoch für den Standardbenutzerraum nicht zu existieren (s)printf.

sdaau
quelle
4

Lösung

Die Funktion btoxkonvertiert beliebige Daten *bbin eine nicht abgeschlossene Folge *xpvon nhexadezimalen Ziffern:

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

Beispiel

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

Ergebnis : 00010A0B.

Live: Tio.run .

7vujy0f0hy
quelle
1

Dies ist eine Möglichkeit, die Konvertierung durchzuführen:

#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
quelle
1

Leicht modifizierte Yannith-Version. Es ist nur so, dass ich es gerne als Rückgabewert habe

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

Mikhail Baynov
quelle
1

Diese Funktion eignet sich, wenn Benutzer / Aufrufer möchten, dass Hex-Zeichenfolgen in ein Zeichenarray / -puffer eingefügt werden. Mit einer Hex-Zeichenfolge in einem Zeichenpuffer kann der Benutzer / Aufrufer ein eigenes Makro / eine eigene Funktion verwenden, um sie an einem beliebigen Ort anzuzeigen oder zu protokollieren (z. B. in einer Datei). Mit dieser Funktion kann der Aufrufer auch die Anzahl der (Hex-) Bytes steuern, die in jede Zeile eingefügt werden sollen.

/**
 * @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));

}

Beispiel: Code

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

AUSGABE

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
quelle
0

In C gibt es dafür kein Grundelement. Ich würde wahrscheinlich einen ausreichend langen Puffer zuordnen (oder vielleicht zuordnen) und die Eingabe durchlaufen. Ich habe es auch mit einer dynamischen String-Bibliothek mit Semantik (aber nicht Syntax!) Ähnlich wie bei C ++ gesehen. Dies ostringstreamist eine plausibel allgemeinere Lösung, aber die zusätzliche Komplexität ist möglicherweise nicht nur für einen Einzelfall wert.

verrückt
quelle
0

Wenn Sie die Hex-Werte in einer char *Zeichenfolge speichern möchten , können Sie verwenden snprintf. Sie müssen Platz für alle gedruckten Zeichen zuweisen, einschließlich der führenden Nullen und des Doppelpunkts.

Erweitern Sie Marks Antwort:

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

Also wird jetzt str_bufdie Hex-Zeichenfolge enthalten.

Mr. Shickadance
quelle
das überschreibt die ersten 2 Zeichen immer und immer wieder .. richtig?
Xordon
0

Die Lösung von ZincX wurde angepasst, um Doppelpunktbegrenzer einzuschließen:

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
quelle
0

Ich werde hier die C ++ - Version für alle Interessierten hinzufügen .

#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.
}

Es wird der Hexdump der bufferLänge countbis gedruckt std::ostream out(Sie können ihn als Standard festlegen std::cout). Jede Zeile enthält bytes_per_lineBytes, jedes Byte wird mit einem zweistelligen Hex in Großbuchstaben dargestellt. Zwischen den Bytes wird ein Leerzeichen stehen. Und am Ende der Zeile oder am Ende des Puffers wird eine neue Zeile gedruckt. Wenn bytes_per_lineauf 0 gesetzt, wird new_line nicht gedruckt. Versuchen Sie es selbst.

WiSaGaN
quelle
0

Zur einfachen Verwendung habe ich eine Funktion erstellt, die die Eingabezeichenfolge (Binärdaten) codiert:

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

Verwendung:

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
quelle
0

Basierend auf Yannuths Antwort, aber vereinfacht.

Hier dest[]wird impliziert, dass die Länge von doppelt so lengroß ist, und die Zuweisung wird vom Anrufer verwaltet.

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
quelle
0

Ich weiß, dass diese Frage bereits eine Antwort hat, aber ich denke, meine Lösung könnte jemandem helfen.

In meinem Fall hatte ich also ein Byte-Array, das den Schlüssel darstellt, und ich musste dieses Byte-Array in ein char-Array mit hexadezimalen Werten konvertieren, um es in einer Zeile auszudrucken. Ich habe meinen Code in eine Funktion wie diese extrahiert:

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

Jetzt kann ich meine Funktion folgendermaßen nutzen:

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

Serialobject ist Teil der Arduino-Bibliothek und m_publicKeyMitglied meiner Klasse mit der folgenden Deklaration uint8_t m_publicKey[32].

Nussknacker
quelle
0

Sie können mit snprintf und malloc lösen.

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
quelle
-2

Was für komplexe Lösungen!
Malloc und Sprints und Casts oh mein Gott. (OZ Zitat)
und nirgendwo ein Rem. Meine Güte,

wie wäre es mit so etwas?

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
quelle
OK, jetzt haben Sie zwei hexadezimale Ziffern. Es bleibt, Trennzeichen hinzuzufügen und sich um die anderen zu konvertierenden Bytes zu kümmern. Vielleicht mit einer Schleife? Machen Sie es zu einer Funktion und Sie haben etwas Ähnliches wie ich (aber ziemlich ausführlich und schwer zu lesen). Vielleicht sollten Sie den Job zumindest beenden, bevor Sie Namen auf anderen Postern nennen?
Kriss
1
Und ein Wort zu Kommentaren im Quellcode (nicht REM, das ist das BASIC-Schlüsselwort für Kommentare, bitte vermeiden Sie das): Kommentare, die auf Englisch sagen, was der Code tut, sind sehr, sehr schlechte Praktiken! Ja, Programmierer sollten wissen, was Modulo-Operatoren bedeuten (geben Sie die Überreste an) und diese Division zählt, wie oft eine Zahl in einer anderen erscheint ... und dass printf das Ergebnis druckt. Oh mein!
Kriss