erste 4 Byte aus Hexfile in INT konvertieren



  • Sooooo,

    Ich habe es hinbekommen das die Ausgabe,sprich das cout das macht was ich will.
    Bloß wie bekomme ich diesen Wert nun auf eine Variable?
    Sprich einen 1 byte Puffer, welcher mir diesen Ausdruck speichert: cout<<hex<<(int)buffer[i];

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
        char buffer[4]={0};
    
        ifstream quelle;
        quelle.open("C:\\Users\\Daffi\\Desktop\\Bearbeiten2", ios::in | ios::binary );
        if (!quelle)                              // Fehler beim Öffnen?
            cerr << "Eingabe-Datei kann nicht geöffnet werden\n"; 
    
            quelle.read(buffer,4);
    
            for (size_t i=0;i<4;i++){
                 cout<<hex<<(int)buffer[i];
    
             }
    
        quelle.close();
        getchar();
        return 0;
    }
    


  • Probier doch mal als buffer gleich int zu nehmen. 😉



  • Sprich einen 1 byte Puffer,

    Ich dachte du wolltest 4 Byte in eine einzige Zahl umwandeln.



  • Nick Unbekannt schrieb:

    Probier doch mal als buffer gleich int zu nehmen. 😉

    Geht nicht, da read ein CHar Array Vorraussetzt.

    Ich dachte du wolltest 4 Byte in eine einzige Zahl umwandeln.

    Ja ist auch der Sinn.
    Ich hab aber lediglich hinbekommen den Hexa String überhaupt mal richtig einzulesen.

    Das Array sieht immo so aus:

    buffer: {0, 0, 4, 62}
    Soll Ergebnis ist {0, 0, 4, 3e}

    Daraus dann ein Int zu bilden ist nicht das Problem, nur dahin komme ich leider nicht!



  • daffi schrieb:

    Nick Unbekannt schrieb:

    Probier doch mal als buffer gleich int zu nehmen. 😉

    Geht nicht, da read ein CHar Array Vorraussetzt.

    Und warum castest du nicht den Zeiger? Oder wenn es unbedingt sein muss, mach eine Union:

    typedef union {
        int wert;
        char bytes[4];
    } LeseHelfer;
    
    LeseHelfer meinwert;
    read(meinwert.bytes, 4);
    cout << meinwert.wert;
    


  • Vicious Falcon schrieb:

    Endian beachten!

    Außerdem kannst du mit einem Cast immer eine beliebige (Byte-) Anzahl von Daten korrekt einlesen.



  • Nick Unbekannt schrieb:

    daffi schrieb:

    Nick Unbekannt schrieb:

    Probier doch mal als buffer gleich int zu nehmen. 😉

    Geht nicht, da read ein CHar Array Vorraussetzt.

    Und warum castest du nicht den Zeiger? Oder wenn es unbedingt sein muss, mach eine Union:

    typedef union {
        int wert;
        char bytes[4];
    } LeseHelfer;
    
    LeseHelfer meinwert;
    read(meinwert.bytes, 4);
    cout << meinwert.wert;
    

    Probiere es aus und du wirst sehen das er absoluten Mist da rein schreibt.
    Hab ich alles auch schon probiert ...

    Bei dir kommt das raus: 3e0400000 ...
    ist nicht ganz das was ich suche,dennoch danke!

    Was mich aber bei dem union noch interessiert,wo weist du der Variable wert einen Wert zu?



  • daffi schrieb:

    Probiere es aus und du wirst sehen das er absoluten Mist da rein schreibt.
    Hab ich alles auch schon probiert ...

    Ich weiß, dass das kein Mist ist. 😉

    daffi schrieb:

    Bei dir kommt das raus: 3e0400000 ...
    ist nicht ganz das was ich suche,dennoch danke!

    Den Tipp mit der Endianness hast du beherzigt?

    daffi schrieb:

    Was mich aber bei dem union noch interessiert,wo weist du der Variable wert einen Wert zu?

    Rate mal was Union heißt? 😉 Die beiden Werte haben den selben Speicherbereich. Du umgehst damit lediglich einen Cast.

    Tipp:
    Um das Problem besser verstehen zu können, schreibe doch einfach erstmal ein int mit write in eine Datei und öffne diese mit einem Hexeditor. Dann sollte auch die Sache mit der Endianness klarer werden.



  • Ok ich sehe das das mit dem Union gar net so doof ist ...
    die Werte sind alle nur verkehrt herum!
    Das meint ihr mit dem Endian.

    Verstehen tue ich den Artikel nicht wirklich.
    Handelt es sich dabei wirklich um eine Computerabhängige Speicherung von Werten?

    Dann wäre es bei mir wohl der little Endian!

    Soll ich nun das Array einfach umsortieren?

    EDIT:

    Habs gefunden ...
    Der Code geht nun.
    Nur die Conversion hab ich noch nicht richtig kapiert.
    Kann mir das noch mal jemand mit eigenen Worten sagen?

    Danke für eure Mühen,Daffi

    int INT_little_endian_TO_big_endian(int i)
    {
        return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
    }
    
    int main()
    {
        int buffer[4]={0};
    
        ifstream quelle;
        quelle.open("C:\\Users\\Daffi\\Desktop\\Bearbeiten2", ios::in | ios::binary );
        if (!quelle)                              // Fehler beim Öffnen?
            cerr << "Eingabe-Datei kann nicht geöffnet werden\n"; 
    
            typedef union {
                int wert;
                char bytes[4];
            } LeseHelfer;
    
            LeseHelfer meinwert;
            quelle.read(meinwert.bytes, 4);
            meinwert.wert=INT_little_endian_TO_big_endian(meinwert.wert);
            cout <<meinwert.wert;
    
        quelle.close();
        getchar();
        return 0;
    }
    


  • daffi schrieb:

    Ok ich sehe das das mit dem Union gar net so doof ist ...
    die Werte sind alle nur verkehrt herum!
    Das meint ihr mit dem Endian.

    Korrekt

    daffi schrieb:

    Verstehen tue ich den Artikel nicht wirklich.
    Handelt es sich dabei wirklich um eine Computerabhängige Speicherung von Werten?

    Was verstehst du nicht? Die Endianness hängt von der CPU ab.

    daffi schrieb:

    Dann wäre es bei mir wohl der little Endian!

    Ja!

    daffi schrieb:

    Soll ich nun das Array einfach umsortieren?

    Nein, warum? Du hast doch deinen int .

    Oder meintest du, die Daten sind in Big-Endian gespeichert? Dann musst du sie drehen. Du kannst dafür aber die Netzwerkfunktion ntohl() verwenden,



  • MH, das Problem ist das das Programm auf diversen Rechnern läuft und somit es auch naheliegt,dass vllt der Endian sich ändert.
    Kann man dem iwie vorbeugen?


  • Mod

    daffi schrieb:

    MH, das Problem ist das das Programm auf diversen Rechnern läuft und somit es auch naheliegt,dass vllt der Endian sich ändert.
    Kann man dem iwie vorbeugen?

    Ja. Auf undefiniertes verhalten wie durch reinterpret_cast und unions verzichten und stattdessen rechnen. Die Elemente deines Arrays stellen Ziffern einer Zahl im 256er System dar (oder genauer gesagt im 2 hoch CHAR_BIT System), damit kannst du dir ganz einfach ausrechnen, welchen Wert die Zahl hat.



  • Die Endianness ist auf den meisten handelsüblichen Rechnern gleich. Bei ARM, x86, x64, überall Little-Endian.
    Zur Sicherheit kannst du dich aber auf eine Endianness festlegen und dann bei Bedarf swappen. Dafür gibt es diese "host to network"-Funktionen die ich dir vorhin vorgestellt habe. Die Netzwerk-Endianness ist Standardmäßig Big-Endian. Die kümmern sich auch darum, herauszufinden welche Endianness dein System hat. Du hast also nichts weiter zu tun, als deinen Wert einmal durch diese Funktion zu führen. Das ganze umgekehrt, wenn du die Werte speichern willst.

    http://www.manpagez.com/man/3/ntohl/
    Steht zwar OSX drunter, die Funktionen gibt es aber auch in Windows und Linux.

    http://msdn.microsoft.com/en-us/library/ms740069(VS.85).aspx



  • SeppJ schrieb:

    daffi schrieb:

    MH, das Problem ist das das Programm auf diversen Rechnern läuft und somit es auch naheliegt,dass vllt der Endian sich ändert.
    Kann man dem iwie vorbeugen?

    Ja. Auf undefiniertes verhalten wie durch reinterpret_cast und unions verzichten und stattdessen rechnen. Die Elemente deines Arrays stellen Ziffern einer Zahl im 256er System dar (oder genauer gesagt im 2 hoch CHAR_BIT System), damit kannst du dir ganz einfach ausrechnen, welchen Wert die Zahl hat.

    Soweit war ich ja auch schon.
    wie gesagt mein Array hatte den Aufbau: {0,0,4,62}

    Ich habe es nicht hinbekommen das es so aussieht: {0,0,4,3E}

    Dannach kann ich ohne Probleme mit *16^x rechnen...



  • daffi schrieb:

    Soweit war ich ja auch schon.
    wie gesagt mein Array hatte den Aufbau: {0,0,4,62}

    Ich habe es nicht hinbekommen das es so aussieht: {0,0,4,3E}

    Die oberen Werte sind Dezimal und die unteren Hexadezimal, dein Ergebnis stimmt also.

    daffi schrieb:

    Dannach kann ich ohne Probleme mit *16^x rechnen...

    Das hab ich ja noch nie gehört, dass man die Byteorder über die Basis korrigiert. Es ist auch eine ganz schlechte Idee dies zu tun, weil extrem langsam. Und auch rein logisch ist es Unsinn, weil ein float ist nunmal kein int .
    Es gibt dafür Funktionen direkt in der CPU und diese sollten auch dafür genutzt werden. Wäre natürlich interessant, ob der Compiler das so hin optimiert bekommt?
    Bei Übertragungen über das Netzwerk entstehen die selben Probleme, also warum soll man sich dann nicht an ihrer Lösung orientieren?



  • Die oberen Werte sind Dezimal und die unteren Hexadezimal, dein Ergebnis stimmt also.

    Ich weis das es stimmt.Ich will doch nur das in den Array die HEX angabe steht und nicht die Dezimale.
    Damit kann ich gar nix anfangen und umwandeln kann ich es irgendwie auch nicht.



  • daffi schrieb:

    Ich will doch nur das in den Array die HEX angabe steht und nicht die Dezimale.

    Das verstehe ich jetzt nicht? Der angezeigte Wert hat nur für dich zur Visualisierung die Basis 16, bzw 10. Im Array stehen auch weiterhin nur binäre Werte.

    daffi schrieb:

    Damit kann ich gar nix anfangen und umwandeln kann ich es irgendwie auch nicht.

    Schau dir mal an, ob deine Byteswap-Funktion das richtige tut, bzw. bist du dir sicher, dass die Werte in der Datei Big-Endian sind?

    Du musst die Werte übrigens verodern und nicht addieren. Und Right-Shift von signed Werten ist auch keine gute Idee.

    http://de.wikipedia.org/wiki/Zweierkomplement



  • [quote="Nick Unbekannt"]

    daffi schrieb:

    Ich will doch nur das in den Array die HEX angabe steht und nicht die Dezimale.

    Das verstehe ich jetzt nicht? Der angezeigte Wert hat nur für dich zur Visualisierung die Basis 16, bzw 10. Im Array stehen auch weiterhin nur binäre Werte.

    daffi schrieb:

    Damit kann ich gar nix anfangen und umwandeln kann ich es irgendwie auch nicht.

    Ok ich versuche es nochmal anders:

    Ziel ist es eine INT Zahl aus dem Array zu bekommen.
    Mein Ansatz war folgender:

    Das Array nehmen und dann jede Stelle mal 16^x nehmen und so die Zahl zusammensetzen.
    Deshalb bräuchte ich das 3e.

    Ich weis leider keinen Eleganteren Weg um dies zu wandeln.



  • daffi schrieb:

    Ich will doch nur das in den Array die HEX angabe steht und nicht die Dezimale.

    Im int bzw. Array steht eine Zahl, und die ist weder dezimal oder headezimal. Du könntest genausogut soundsoviel Finger zählen oder Steinchen legen. Entscheidend ist, wie Du diese Zahl anzeigst.

    Als standard gibt cout int-Zahlen dezimal aus. Wenn Du sie anders haben willst, kannst Du das umschalten mit:

    cout << hex << meineVariable << endl;
    

    Wenn Du noch etwas mehr Format reinhaben willst, informiere Dich über setw und setfill : http://www.cplusplus.com/reference/iostream/manipulators/setw/.

    Übrigens ist die Endianess auf Power-PC-Prozessoren Big-Endian und damit anders als Intel. Spielt keine Rolle, solange man nur ints miteinander verrechnet, aber, wie Du gesehen hast, wenn man liest oder speichert. Da gibt es nur eines: Ein fixes Format vereinbaren, damit alle Rechner wissen, was in der Datei drinsteht.



  • Was spricht jetzt eigentlich dagegen die "host to network byteorder"-Funktionen zu nutzen, die ich dir vorhin verlinkt habe? Damit brauchst du dir über die Endianness überhaupt keinen Kopf mehr zu machen. Das wird alles für dich erledigt, du musst lediglich sicherstellen, dass auf jedem System diese Funktion zum Schreiben/Lesen in/aus der Datei genutzt werden.


Anmelden zum Antworten