2016-04-06 15 views
2

Ich muss eine Hex-Zeichenfolge in eine ASCII-Zeichenfolge konvertieren. Sie können es nicht nur mit einer printf anzeigen, sondern auch speichern. Ich benutze diesen Code, um es anzuzeigen, aber ich möchte es speichern. Wie kann ich tun ?:So konvertieren Sie einen Hex-Zeichen-Puffer in eine ASCII-Zeichenfolge [C]

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

int hex_to_int(char c){ 
     int first = c/16 - 3; 
     int second = c % 16; 
     int result = first*10 + second; 
     if(result > 9) result--; 
     return result; 
} 

int hex_to_ascii(char c, char d){ 
     int high = hex_to_int(c) * 16; 
     int low = hex_to_int(d); 
     return high+low; 
} 

int main(){ 
     const char st[12] = "48656C6C6F3B"; 
     int length = strlen(st); 
     int i; 
     char buf = 0; 
     for(i = 0; i < length; i++){ 
       if(i % 2 != 0){ 
         printf("%c", hex_to_ascii(buf, st[i])); 
       }else{ 
         buf = st[i]; 
       } 
     } 
} 

Meine erste Lösung sprintf(buf,"%c",hex_to_ascii(buf,st[i]) int die for-Schleife zu verwenden, aber diese Lösung funktioniert nicht, weil sprintf einen Zeiger von char benötigen.

+2

'sprintf()' sicherlich brauchen keinen Zeiger für die '% c 'Konvertierung. Aber wenn Sie den Charakter haben, der alles ist, was Sie brauchen, speichern Sie es einfach. – unwind

+0

Bei der Umwandlung einer "Hex-Zeichenkette" in eine "ASCII-Zeichenkette" hängt das Design von Dingen ab, die hier nicht definiert sind: 1) Wird die Hex-Zeichenkette immer wohlgeformt und wenn nicht, was sollte das Ergebnis sein? 2) Griff A-F und a-f? 3) Was reserviert den Puffer für die resultierende Zeichenfolge? 4) Wie behandelt man "00"? 5) Portable zu Nicht-ASCII? – chux

Antwort

2

Okay, lassen Sie uns einen Schuss haben:

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

static unsigned char hexdigit2int(unsigned char xd) 
{ 
    if (xd <= '9') 
    return xd - '0'; 
    xd = tolower(xd); 
    if (xd == 'a') 
    return 10; 
    if (xd == 'b') 
    return 11; 
    if (xd == 'c') 
    return 12; 
    if (xd == 'd') 
    return 13; 
    if (xd == 'e') 
    return 14; 
    if (xd == 'f') 
    return 15; 
    return 0; 
} 

int main(void) 
{ 
    const char st[] = "48656C6C6F3B", *src = st; 
    char text[sizeof st + 1], *dst = text; 

    while (*src != '\0') 
    { 
    const unsigned char high = hexdigit2int(*src++); 
    const unsigned char low = hexdigit2int(*src++); 
    *dst++ = (high << 4) | low; 
    } 
    *dst = '\0'; 
    printf("Converted '%s', got '%s'\n", st, text); 
    return 0; 
} 

Die sehr ausführliche aussehende digit2int() Funktion versucht, nicht ASCII-abhängig sein, das ist immer schön. Beachten Sie, dass die Schleife in main() eine korrekte Eingabe voraussetzt, sie prüft nur alle zwei Zeichen auf Beendigung und verarbeitet keine Nicht-Hex-Daten.

Oh, und diese Drucke:

Converted '48656C6C6F3B', got 'Hello;' 
+0

@chux Sicher, warum nicht. Refactoring ist schließlich Leben. Fertig, danke. – unwind

0

wie Sie wahrscheinlich wissen, jeder character is represented by an int -> ... 'a' = 97, 'b' = 98 ... so, wenn Sie ein hex in int konvertieren, ist es nicht notwendig, eine andere Funktion zu erstellen ascii - Nur durch Speichern der ganzen Zahl in einem Charakter wird der Trick (es sei denn, ich verpasse etwas, das die Übung zu verstehen).

wie es zurück in den Speicher zu speichern: Es gibt viele Möglichkeiten: 1. const entfernen, bevor const char st[12] = "48656C6C6F3B"; und zuweisen den Rückgabewert von der Funktion zu der gewünschten Zelle oder mit sscanf

here einen Blick

0

Sie haben alles gut gemacht, aber es gibt einige Probleme. Vergleichen Sie mit den folgenden:

const char* st = "48656C6C6F3B"; // I don't want to calculate storage size 
char r[12] = { 0 }; // Here is I want to store the result 
char* h = r; // pointer to write position in the result 
int length = strlen(st); 
for (int i = 0; i < length; i+=2) { 
    assert((h - r) < sizeof(r)); // check that there is not problem with out of range 
    *h++ = hex_to_ascii(st[i], st[i + 1]); 
} 
printf("%s", r); // now the r contains "ansi string" 
0

zu "retten" das Ergebnis, fügen Sie einfach einen Puffer, dest, um das Ergebnis zu speichern.

Zusätzliche Vorschläge im Code enthalten.

// add void to signature 
int main(void) { 
    const char st[12] = "48656C6C6F3B"; 
    int length = strlen(st); 
    int i; 
    char buf = 0; 

    // add destination buffer 
    char dest[10]; 

    // Add test 
    // for (i = 0; i < length; i++) { 
    for (i = 0; i < length && (i/2 + 1) < sizeof(dest); i++) { 
    if (i % 2 != 0) { 

     // printf("%c", hex_to_ascii(buf, st[i])); 
     dest[i/2] = hex_to_ascii(buf, st[i]); 

    } else { 
     buf = st[i]; 
    } 
    } 

    // Add termination 
    dest[i/2] = '\0'; 
    // Do someting with dest 
    puts(dest); 
    return 0; 
} 

Alternativ kann einige Code, die verschiedene mögliche Probleme behandelt: Groß-/Kleinschreibung hexadezimale Ziffern, ungültige Zeichen, ungeradee Zählung kleine Puffer, eingebettete Null-Zeichen.

#include <stdlib.h> 
#include <string.h> 
// There are _many_ ways to do this step. 
unsigned char2digit(int ch) { 
    static const char Hex[] = "ABCDEFabcdef"; 
    char *p = memchr(Hex, ch, 32); 
    if (p) { 
    return (unsigned) (p - Hex) % 16; 
    } 
    return (unsigned) -1; // error value 
} 

// Return NULL with ill-formed string 
char *HexStringToString(char *dest, size_t size, const char *src) { 
    char *p = dest; 
    if (size <= 0) { 
    return NULL; 
    } 
    size--; 
    while (*src) { 
    if (size == 0) return NULL; 
    size--; 

    unsigned msb = char2digit(*src++); 
    if (msb > 15) return NULL; 
    unsigned lsb = char2digit(*src++); 
    if (lsb > 15) return NULL; 
    char ch = (char) (msb * 16 + lsb); 

    // Optionally test for embedded null character 
    if (ch == 0) return NULL; 

    *p++ = ch; 
    } 
    *p = '\0'; 
    return dest; 
} 

void testHex(const char *s) { 
    char buf[10]; 
    char *dest = HexStringToString(buf, sizeof buf, s); 
    printf("%-24s --> '%s'\n", s, dest ? dest : "NULL"); 
} 

#include <stdio.h> 
int main(void) { 
    testHex("48656C6C6F3B");  // upper case 
    testHex("48656c6c6f3b");  // lower case 
    testHex(""); 
    testHex("48656C6C6F3B48656C"); 
    // fails 
    testHex("48656C6C6F3B48656C6C"); // Too long 
    testHex("48656C6C6F3B0");  // Odd character count 
    testHex("48656C6C6F3Bxx");  // Non-hex character 
    testHex("48006C6C6F3B");   // null character 
    return 0; 
}   

Ausgabe

48656C6C6F3B    --> 'Hello;' 
48656c6c6f3b    --> 'Hello;' 
         --> '' 
48656C6C6F3B48656C  --> 'Hello;Hel' 
48656C6C6F3B48656C6C  --> 'NULL' 
48656C6C6F3B0   --> 'NULL' 
48656C6C6F3Bxx   --> 'NULL' 
48006C6C6F3B    --> 'NULL'