5 Byte long long in 4x 10 Bit splitten mit Bitmask



  • Hallo allerseits,

    ich versuche es mal wieder und gebe mir mit der Formulierung des Problems diesmal allergrößte Mühe.

    Ich hole aus einer Binärdatei 5 Byte als long long.
    Diese 5 Byte möchte ich mit Bitmask 10-Bit-weise splitten.

    In dem 5 Byte "long long" -> 104421492835
    verstecken sich folgende int: 97, 256, 98, 99

    Die 98 und 99 werden korrekt rausgeholt, bei 256 werden jedoch 10 Nullen rangestellt, bei 97 sogar 20.

    Hier mal der Code-Ausschnitt:

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    int main() {
    
    	long long value = 104421492835;
    	long bitmask4 = 1023;
    
    	int zahl4 = value&bitmask4; //Passt
    
    	long bitmask3 = bitmask4 << 10;
    	int zahl3 = (value&bitmask3) >> 10; //Passt
    
    	long bitmask2 = bitmask3 << 10;
    	int zahl2 = (value&bitmask2) >> 10; //Es werden 10 Nullen angehängt
    
    	long bitmask1 = bitmask2 << 10;
    	int zahl1 = (value&bitmask1) >> 10;	//Es werden 20 Nullen angehängt
    
    	cout << zahl1 << endl;
    	cout << zahl2 << endl;
    	cout << zahl3 << endl;
    	cout << zahl4 << endl;
    
    	getchar();
    
    }
    

    Wo ist denn dort der Fehler?

    Vielen Dank vorab.



  • 10
    20
    30



  • Willst Du vielleicht um 20 respektive 30 bit nach rechts shiften in den letzten beiden Fällen?
    Wenn Du die Ausgangszahl direkt shiftest, bräuchtest Du auch nur eine Maske...



  • Erstmal vielen Dank für die Antworten!!!

    Jetzt habe ich noch ein (für mich) seltsames Problem.
    In dem Code-Beispiel oben funktioniert natürlich alles, aber mir fällt auf,
    dass beim Schreiben der 5 Byte in die Binärdatei alles glatt läuft und korrekt ist.

    Lese ich nun aber diese 5 Byte wieder aus, wird aus dem ursprünglichen positiven, plausiblen Wert (long long value) ein negativer, wodurch ich mir die Zahl1 versaue.

    Habt Ihr da vielleicht eine Idee, woran das generell liegen kann.

    Hier die Methode, wie ich sie nutze:

    void codeAusBinaerDatei() {
    
        //int intCode = 0;
        //string s;
        fstream bind;
    	long long value;
    	long bitmask4 = 1023;
    
    	int durchlauf = 2;
    
        bind.open("code.bin", ios::in|ios::binary);     
    
    	for (int i = 0; i < 1; i++) {
    		bind.read((char*)&value, 5);
    
    		cout << "Value: " << value << endl;
    
    		int zahl4 = value&bitmask4; //Passt
    
    		long bitmask3 = bitmask4 << 10;
    		int zahl3 = (value&bitmask3) >> 10; //Passt
    
    		long bitmask2 = bitmask3 << 10;
    		int zahl2 = (value&bitmask2) >> 20; //Es werden 10 Nullen angehängt
    
    		long bitmask1 = bitmask2 << 10;
    		int zahl1 = (value&bitmask1) >> 30;	//Es werden 20 Nullen angehängt
    
    		cout << zahl1 << endl;
    		cout << zahl2 << endl;
    		cout << zahl3 << endl;
    		cout << zahl4 << endl;
    
    	}
    
    		bind.close();     
    
    }
    

    Genauer gesagt wird der Zahl1 nun folgendes vorangestellt:

    11001100110011001100



  • setz vorher value mal auf 0



  • Es gibt da 3 Bytes, die sich von Anfang an vernachlässigt fühlen... Und Bytes können wirklich fies werden!



  • Ich wär mal für Thread-Mutexe hier, damit der Volkard-Low-Latency-Realtime-Task frühzeitig Besitz der Ressource anzeigen kann.



  • Fischi2k schrieb:

    bind.read((char*)&value, 5);
    

    Autsch!



  • wasn?


  • Mod

    decimad schrieb:

    wasn?

    Endianess und so.



  • Ja, das. Und 5 Bytes in nen long long reinlesen fühlt sich einfach falsch an. Auch wenn man die Plattform genau kennt, vorher auf Null setzt (was hier ja vergessen wurde) und immer schon Cowboy-Programmierer sein wollte...
    Es schmerzt.



  • Fischi2k schrieb:

    void codeAusBinaerDatei() {
    
        //int intCode = 0;
        //string s;
        fstream bind;
    	long long value;
    	long bitmask4 = 1023;
    
    	int durchlauf = 2;
    
        bind.open("code.bin", ios::in|ios::binary);     
    
    	for (int i = 0; i < 1; i++) {
    		bind.read((char*)&value, 5);             // <----------- value mit 0 initialisieren!!!
    
    		cout << "Value: " << value << endl;
    
    		int zahl4 = value&bitmask4; //Passt
    
    		long bitmask3 = bitmask4 << 10;
    		int zahl3 = (value&bitmask3) >> 10; //Passt
    
    		long bitmask2 = bitmask3 << 10;
    		int zahl2 = (value&bitmask2) >> 20;     //Es werden 10 Nullen angehängt (wirklich???)
    
    		long bitmask1 = bitmask2 << 10;         // <---- integer overflow falls, sizeof(long)==4
    		int zahl1 = (value&bitmask1) >> 30;	//Es werden 20 Nullen angehängt
    
    		cout << zahl1 << endl;
    		cout << zahl2 << endl;
    		cout << zahl3 << endl;
    		cout << zahl4 << endl;
    	
    	}
    
    		bind.close();     
        
    }
    

    Genauer gesagt wird der Zahl1 nun folgendes vorangestellt:

    11001100110011001100

    mfg Martin



  • Wow,

    Erstmal wieder vielen Dank. Werde mich gleich mal ran setzen und versuchem, die Vorschläge umzusetzen.

    Wie sollte ich denn besser die 5 Byte einlesen?

    Dieser Vorschlag kam von meinem Dozenten, ein junger Dr. der Informatik. Das hätte ich nie angezweifelt. 😞



  • Fischi2k schrieb:

    Wie sollte ich denn besser die 5 Byte einlesen?

    Ich würde anfangen in dieser Richtung zu planen:

    class BitWriter{
      …
       void putBit(bool bit){
          buf=(buf<<1)|bit;
          ++count;
          if(count==8){
             out.putChar(buf);
             count=0;
          }
       }
    

    Leser bauen, der das auch kann. Später flush() in den Destruktor. putBits. putBits optimieren, statt auf putBit aufzusetzen.

    Aber das könnte im Momentchen noch außer Deiner Reichweite sein. Hmm…
    Aber der Packer wäre dann durchaus einfacher, hab ich so ein Gefühl.

    edit:

    unsigned long long buf=0;
    
    //5*8 lesen
    for(int i=0;i!=5;++i){
       unsigned char byte=in.get();
       buf=(buf<<8)|byte;
    }
    
    //4*10 schreiben
    for(int i=0;i!=4;++i){
       cout<<(buf&1023);
       buf>>=10;
    }
    
    //dabei reihenfolge verdreht. war dir wichtig?
    


  • Fischi2k schrieb:

    Wow,

    Erstmal wieder vielen Dank. Werde mich gleich mal ran setzen und versuchem, die Vorschläge umzusetzen.

    Wie sollte ich denn besser die 5 Byte einlesen?(

    So wie Du's gemacht hast, geht es schon auf LITTLE-ENDIAN Systemen. Du mußt halt die Variable mit 0 initialisieren, oder hinterher die oberen 3 bytes ausmaskieren.

    value &= 0xFFFFFFFFFF;
    

    Denke aber: Auf Rechnern mit BIG-Endian (z.B. PowerPC) hast Du verloren.

    Fischi2k schrieb:

    Dieser Vorschlag kam von meinem Dozenten, ein junger Dr. der Informatik. Das hätte ich nie angezweifelt. 😞

    Halt ein Greenhorn.

    mfg Martin



  • Ah okay, danke.

    Mein Problem ist damit vorerst gelöst.
    Daher nochmal ein fettes "DANKE" an euch alle.
    Habt mir wirklich sehr geholfen.



  • Doch noch nicht so ganz.

    Vorsicht, es kommt bestimmt eine blöde Frage jetzt, aber:

    void codeAusBinaerDatei() {
    
        fstream bind;
    	long long value = 0;
    	long bitmask4 = 1023;
    
    	int durchlauf = 2;
    
        bind.open("code.bin", ios::in|ios::binary);     
    
    	for (int i = 0; i < 2; i++) {
    		bind.read((char*)&value, 5);
    
    		cout << "Value: " << value << endl;
    
    		int zahl4 = value&bitmask4; //Passt
    
    		long bitmask3 = bitmask4 << 10;
    		int zahl3 = (value&bitmask3) >> 10; //Passt
    
    		long bitmask2 = bitmask3 << 10;
    		int zahl2 = (value&bitmask2) >> 20; //Passt 
    
    		long bitmask1 = bitmask2 << 10;
    		int zahl1 = (value&bitmask1) >> 30;	//Passt
    
    		cout << zahl1 << endl;
    		cout << zahl2 << endl;
    		cout << zahl3 << endl;
    		cout << zahl4 << endl;
    
    		value = value << 10;
    
    	}
    
    		bind.close();       
    }
    

    Wie hole ich mir denn jetzt die nächsten 5 Byte ab?



  • Hat sich erledigt, sorry.

    Hatte zu Testzwecken die Methode zum Schreiben in die Binärdatei zu sehr beschränkt.



  • "Autsch" hilft auf jedenfall niemandem, ganz besonders nicht dem OP.



  • @decimad
    Doch, wie man sieht schon.
    Wenn es ihn interessiert, fragt er nach.
    Wenn nicht, dann spar ich mir die Mühe zu erklären was er eigentlich falsch macht, bzw. was das (potentielle) Problem ist.


Anmelden zum Antworten