C / Hex-Dump programmieren.



  • Ahoi hoi und grüezi wohl.

    Alleine des probierens und des anwenden des gelernten, programmierte ich ein Hexdump programm.
    Jetzt geht es mir um feedback, da es nur ein Hobby meinerseits ist und ich keinen "Lehrer" oder des gleichen habe um dazuzulernen.

    Ich habe nur meine Bücher wo ich mein Wissen her hole.

    /* hexdump.c */
    #include <stdlib.h>  /*  exit()  */
    
    void hexPrint(FILE *fd)
    {
        int  chr;
        char buffer[17];
        int  b  = 0;
        int  *i = &b;
    
        while((chr = fgetc(fd)) != EOF)
        {
            printf("%02X ", chr);
            if(chr < 126 && chr > 32)
            {
                buffer[*i] = (char)chr;
            }
            else
            {
                buffer[*i] = '.';
            }
    
            *i += 1;
    
            if(*i == 16)
            {
                buffer[*i + 1] = '\0'; // 0 terminator at the end.
                printf("  ->   ");
                for(int c = 0; c < 16; c++)
                {
                    printf("%c", buffer[c]);
                }
                puts("");
                *i = 0;
            }
        }
        /* lets print the rest...
         * if the file has no % 16 = 0 signs...
         */
         if(*i == 0)
         {
             exit(0);
         }
         else
         {
            for(int rest = (*i % 16); rest < 16; rest++)
            {
                printf("   ");
            }
            printf("  ->   ");
            for(int rest_c = 0; rest_c < *i; rest_c++)
            {
                printf("%c", buffer[rest_c]);
            }
            puts("");
        }
    }
    
    /* hexdump.h */
    #ifndef __HEXDUMP_H__
    #define __HEXDUMP_H__
    
    #include "hexdump.c"
    
    void hexPrint(FILE *fd);
    
    #endif
    
    /* main.c */
    /*  STD HEADERS  */
    #include <stdio.h>
    #include <errno.h>
    
    /*  OWN HEADERS  */
    #include "hexdump.h"
    
    /* MAIN FUNCTION */
    int main(int argc, char *argv[])
    {
        FILE *fd = NULL;
    
        // Check arguments
        if(argc != 2)
        {
            fprintf(stderr, "Usage: %s [FILENAME]\n", argv[0]);
            return 1;
        }
    
        // check fopen
        if((fd = fopen(argv[1], "r")) < 0)
        {
            perror("File open failed...\n");
            return 1;
        }
    
        // lets print the hex dump from file...
        hexPrint(fd);
    
        fclose(fd);
        return 0;
    }
    

    Ist dies so akzeptabel ? UND jetzt noch die frage
    mein Programm funktioniert einwandfrei soweit und auch wird alles korrekt angezeigt, NUR:

    Jage ich die gleiche text.txt z.b. durch das programm hexdump ("debian linux") wird z.b. 0AF9 angezeigt, bei meinem F90A, trotzdem stimmen die strings und sonst alles genau gleich. woran kann das liegen ?

    Ich grüsse Euch freundlichst.

    ---

    clang geht ohne -std=c11, bei gcc mit -std=c11 😉 aber ich denke das wissen hier eig. alle 😉



  • fichtl schrieb:

    Ist dies so akzeptabel ? UND jetzt noch die frage
    mein Programm funktioniert einwandfrei soweit und auch wird alles korrekt angezeigt ...

    Passt doch, Alter. C ist eine Sprache für Praktiker. Wenn dein Code funzt und auch an den (definierten) Rändern keine Anomalien aufweist, dann ist alles gut. 🙂



  • Schöner Pufferüberlauf bei

    if(*i == 16)
    {
        buffer[*i + 1] = '\0';
        /* ... */
    }
    

    😉

    Und warum verwendest du immer '*i' statt einfach nur 'b'?

    Außerdem entferne

    #include "hexdump.c"
    

    aus dem Header und kompiliere (und linke) dann diese Datei zusammen mit der "main.c".



  • Th69 schrieb:

    Schöner Pufferüberlauf bei

    if(*i == 16)
    {
        buffer[*i + 1] = '\0';
        /* ... */
    }
    

    Wie kommst du darauf, dass bei buffer[*i + 1] nichts mehr ist?



  • Andromeda schrieb:

    Wie kommst du darauf, dass bei buffer[*i + 1] nichts mehr ist?

    *i + 1 an der Stelle ist 17.

    char buffer[17];
    

    Das letzte Element ist 16. Typischer Anfängerfehler, bei Arrays und Pointer nicht bei 0 anfangen zu zählen.



  • Ahhhh

    Danke der antworten, nein mir ist schon lange bewusst, bei arrays ist bei 0 anzufangen. 🙂

    Der denkfehler ist folgender:

    Ich lese ja in den buffer 16 zeichen ein und dann muss ja noch der '\0' terminator platz haben, macht 16 + 1 = 17. also brauch ich ein array mit platz für 17 chars. Aber stimmt, ihr habt mir den denkfehler trotzdem aufgezeigt:

    Array mit 16 chars und nicht als string gebraucht wird, braucht auch kein '\0' 😉

    edit: jaaaaa mir ist der denkfehler grad sehr sehr bewusst geworden 😉 vergesst das obere 😉
    ----------------

    und dass mit dem

    #include "hexdump.c"
    

    entfernen werde ich auch machen, aber was hat es für einen grund ?
    Ist includen resourcen verbrauchender als selber linken ? oder ist es der übersichts halber ?

    Grüss Euch


  • Mod

    Andromeda schrieb:

    fichtl schrieb:

    Ist dies so akzeptabel ? UND jetzt noch die frage
    mein Programm funktioniert einwandfrei soweit und auch wird alles korrekt angezeigt ...

    Passt doch, Alter. C ist eine Sprache für Praktiker. Wenn dein Code funzt und auch an den (definierten) Rändern keine Anomalien aufweist, dann ist alles gut. 🙂

    Du sagst "Praktiker", du beschreibst "Stümper".



  • Gib vor der 1. Spalte noch den Offset in der Datei mit aus und puts(""); finde ich auch etwas Merkwürdig.

    printf("%c", ist auch ein Kandidat für eine andere Funktion.
    Du möchtest da ein Zeichen ausgeben.
    Wie man ein Zeichen einliest weißt du ja.

    Und schau dir mal die Funktionen aus ctype.h an.
    Da ist auch was dabei, um zu prüfen, ob das Zeichen druckbar ist.

    fichtl schrieb:

    Ist includen resourcen verbrauchender als selber linken ? oder ist es der übersichts halber ?

    Linken ist der vorgesehene Weg.
    Du kannst die Abhängigkeiten besser überblicken.

    PS. Du plenkst



  • SeppJ schrieb:

    Andromeda schrieb:

    fichtl schrieb:

    Ist dies so akzeptabel ? UND jetzt noch die frage
    mein Programm funktioniert einwandfrei soweit und auch wird alles korrekt angezeigt ...

    Passt doch, Alter. C ist eine Sprache für Praktiker. Wenn dein Code funzt und auch an den (definierten) Rändern keine Anomalien aufweist, dann ist alles gut. 🙂

    Du sagst "Praktiker", du beschreibst "Stümper".

    Nope, nicht umsonst sprach ich von "definierten Rändern". Wenn der Code in einem bestimmten Bereich tut, was er tun soll, dann ist er gut und richtig. The Sprit of C, Alter. C++-ler kapieren das nicht. Ist aber egal. 🙂


  • Mod

    Andromeda schrieb:

    Nope, nicht umsonst sprach ich von "definierten Rändern". Wenn der Code in einem bestimmten Bereich tut, was er tun soll, dann ist er gut und richtig. The Sprit of C, Alter. C++-ler kapieren das nicht. Ist aber egal. 🙂

    Aha, zum Beispiel, dass es ok ist einen Pufferüberlauf zu haben, so lange es funktioniert? Klar!

    Bist du eigentlich so eine Art Internet Agent Provocateur? Erst lässt du alle Nicht-Nazis in NadrW dumm aussehen, alleine weil sie dich auf ihrer Seite haben und daher mit deinem dummen Gehabe assoziiert werden; und nun alle C-Programmierer (zu denen übrigens auch ich zähle, aber das jemand auch mehrere Dinge sein kann ist ja absolut unvorstellbar für dich und dein primitives Schubladendenken).



  • SeppJ schrieb:

    Aha, zum Beispiel, dass es ok ist einen Pufferüberlauf zu haben, so lange es funktioniert? Klar!

    Genau das. Habe ich tatsächlich schon erlebt. Der Einfachheit halber wurde stumpf weitergezählt, in einem schwachbrüstigen System, das per Bit-Banging mit der Außenwelt kommunizierte, um Taktzyklen zu sparen. Dem braven C++-Coder würden die Haare zu Berge stehen.

    SeppJ schrieb:

    Bist du eigentlich so eine Art Internet Agent Provocateur? Erst lässt du alle Nicht-Nazis in NadrW dumm aussehen, alleine weil sie dich auf ihrer Seite haben und daher mit deinem dummen Gehabe assoziiert werden; und nun alle C-Programmierer (zu denen übrigens auch ich zähle, aber das jemand auch mehrere Dinge sein kann ist ja absolut unvorstellbar für dich und dein primitives Schubladendenken).

    Ich kenne halt den ganzen Scheiß aus der Praxis. Das trifft auch auf die Nazis aus NadrW zu. Schmeiß mich doch raus, wenn du mich nicht ertragen kannst. Das ist mir sowas von egal. 🙂



  • Andromeda schrieb:

    Genau das. Habe ich tatsächlich schon erlebt. Der Einfachheit halber wurde stumpf weitergezählt, in einem schwachbrüstigen System, das per Bit-Banging mit der Außenwelt kommunizierte, um Taktzyklen zu sparen.

    Auf Assembler-Ebene ist das vielleicht OK - also da, wo die Maschine die Regeln vorgibt.
    Bei C und C++, wo ein Standard vorgibt, was erlaubt und was UB ist, kann aus dem ganzen Programm schnell kompletter Unsinn werden. Selbst wenn das Verhalten für die Zielmaschine definiert ist - der Standard sagt was anderes, und nach dem richtet sich der Compiler, oder sollte sich richten.

    Andromeda schrieb:

    Schmeiß mich doch raus, wenn du mich nicht ertragen kannst. Das ist mir sowas von egal. 🙂

    Da, wo ich herkomme, heißt es kürzer: "Do it, faggot!"

    Und ich täte. Oh, und wie ich täte.



  • genial ich danke sehr.

    also printf("... wurde schon mal durch fputc() ersetzt und mit:

    #include <ctype.h>
    

    hab ich jetzt isgraph() entdeckt und es funktioniert auch immer noch super.

    AHHH ja !!

    char buffer[16];
    
    *i += 1;
    
            if(*i == 16)
            {
                printf("  ->   ");
                for(int c = 0; c < 16; c++)
                {
                    fputc(buffer[c], stdout);
                }
                puts("");
                *i = 0;
            }
    

    😃

    Genial die hilfe hier, ihr habt grossen Dank. 🙂



  • printf("  ->   ");
    for(int c = 0; c < 16; c++)
    {
        fputc(buffer[c], stdout);
    }
    puts("");
    i = 0;
    

    Warum nicht:

    printf("  ->   %16s\n",buffer);
    

    ?



  • joooo genau, das war auch mein ursprünglicher plan, aber aus dem denkfehler, bastelte ich diesen Müll.

    Was soll ich sagen, man lernt nie aus. 😉

    Vielen dank nochmals.

    und ein schönes wochenende.

    Tante edit meint:

    ich wusste es es geht nicht ohne '\0' wenn ich es wieder als string ausgeben will 😉

    if(*i == 16)
            {
                buffer[*i] = '\0';
                printf("  ->   %s\n", buffer);
                *i = 0;
            }
    

    und es läuft wie geschmiert. 🙂

    Jetzt eben noch die frage:
    Bei meinem Programm, zeigt es den dump einer file z.b. 0AF3 und wenn ich die selber file mit hexdump bearbeit F30A an. Aber der Text neben an ist korrekt, also kein vertauschen oder ähnliches.



  • fichtl schrieb:

    ich wusste es es geht nicht ohne '\0' wenn ich es wieder als string ausgeben will

    Zeichensetzung würde deinen Sätzen verdammt gut tun.

    fichtl schrieb:

    und es läuft wie geschmiert.

    Vorrausgesetzt, dass immer noch char buffer[16] gilt: nein, tut es nicht. Damit bist du genau wieder beim Problem der letzten Seite: 16 Elemente im Array, und mit Index 16 greifst du auf das 17. Element zu. UB, yadayada.

    printf muss eh dein Array durchgehen, um jeden Buchstaben in die Ausgabe zu schreiben. Oder ConsoleWrite / write / wie immer der Syscall am ende heißt. Da kannst du dir das Setzen von NUL an sich auch sparen und direkt die Länge verwenden; ich behaupte, dass es kaum nachprüfbare Performanceeinbußen hat (und "nachprüfbar" ist noch mal eine ganze Ecke kleiner als "spürbar"). Also lass es doch auf 16 Zeichen und verwende "%16s" .

    fichtl schrieb:

    Bei meinem Programm, zeigt es den dump einer file z.b. 0AF3 und wenn ich die selber file mit hexdump bearbeit F30A an. Aber der Text neben an ist korrekt, also kein vertauschen oder ähnliches.

    Hexdumb interpretiert die Daten an dieser Stelle vermutlich als uint16_t , und du bist vermutlich auf einer Little-Endian Maschine. Sind meines Wissens alle x86 und x64. Deswegen sind die Werte vertauscht.

    Du allerdings holst dir die Werte Byteweise. Da wird nichts vertauscht.



  • dachschaden schrieb:

    Andromeda schrieb:

    Genau das. Habe ich tatsächlich schon erlebt. Der Einfachheit halber wurde stumpf weitergezählt, in einem schwachbrüstigen System, das per Bit-Banging mit der Außenwelt kommunizierte, um Taktzyklen zu sparen.

    Auf Assembler-Ebene ist das vielleicht OK - also da, wo die Maschine die Regeln vorgibt.

    Im Prinzip ist C eine generalisierte Assemblersprache. Du kannst oder musst mit vielen maschinennahen Elementen wie Registern, Speicheradressen, Bitbreiten usw. hantieren. Du kannst portables C coden, wie auch solches, das nur auf deinem Prozessor läuft. Die Flexibilität von C ist unschlagbar.

    Das ist vermutlich eine wesentliche Eigenschaft dieser Sprache, die sie viele Jahrzehnte nach ihrer Entstehung immer noch zu den am meisten genutzten Programmiersprachen macht. Solange es Computer gibt, die sich nach Flynn klassifizieren lassen, wird der Siegeszug von C ungebrochen sein. 🙂



  • Andromeda schrieb:

    Im Prinzip ist C eine generalisierte Assemblersprache.

    Nicht, wo dir der Standard sagt, dass es UB ist. Wenn dir das nicht gefällt, musst du die entsprechenden Module/Funktionen in Assembler programmieren. Sonst kann es irgendwann krachen, und du bist dafür verantwortlich. So einfach.



  • Guten Morgen.

    Ja das mit den Satzzeichen, dafür entschuldige ich mich.

    Also, ja , das mit dem '\0' führte wieder zum gleichen Problem, aber:

    printf("  ->   %16s\n", buffer);
    

    Gab dann so eine ausgabe:

    68 61 6C 6C 6F 0A 6B 65 72 7A 65 20 72 75 6C 65   ->   hallo.kerze.herr�q&�e
    

    Eig. sollte bei herr dann fertig sein.

    Grüsse Euch



  • Ich bin doof. Habe den Punkt vergessen: "%.16s" .


Log in to reply