BinaryParser



  • fit schrieb:

    Hi, vielen Dank schonmal für Eure Antworten.

    @mathik:
    Was meinst Du mit Speicherleck ?
    Meinst Du, dass zu dem mit new angelegten char-Array kein entsprechendes delete existiert ?
    Jo stimmt, aber wie soll ich das realisieren, damit das Prog noch einigermassen hübsch im Handling ist ?
    Wenn ich jetzt z.b. eine Methode free() für die Klasse baue oder direkt nach dem benutzen immer lösche, wird leidet die Schnittstelle.

    Aber ihr habt recht, ich arbeite viel zu viel mit Kopien und zu wenig mit Referenzen.

    Jetzt ist aber das Problem, dass ich so nicht weiss, wie ich z.b. die Methode getChar(int) einfach nur eine Referenz auf die angeg. chars zurückgeben lasse, weil ich ja nicht das ganze data zurückgebe, sondern nur einen Teil davon.

    Wie mache ich das ?
    Ich kenn mich da nicht so aus, weil ich vorher von Java verwöhnt wurde 🙄 .

    //entweder (ist am einfachsten)
    
     void getChar(std::string& retVal, int num);
    
     //oder: (ist nicht sonderlich performant)
     std::string getChar(int num); 
    
      //oder auto_ptr verwenden... ungefähr so (eleganteste lösung)
      auto_ptr<string> getChar(int num);
    

    Gruß mathik



  • @mathik: Thx erstmal.

    //entweder (ist am einfachsten) 
     void getChar(std::string& retVal, int num);
    

    Also das will ich nicht nehmen, weil das Konzept so gedacht war, das die Ergebnisse immer als return-Wert zurück kommen sollen.

    //oder: (ist nicht sonderlich performant) 
     std::string getChar(int num);
    

    das wuerde passen, die Implementierung ist aber sicher nicht der Hit (habe vorher fast nie mit std::string gearbeitet):

    //...
    string getChar(int num){
            string retVal;
            retVal.resize(num);
            for(int i=0; i<num; ++i){
                    retVal[i] = data[pos +i];
            }
            pos +=num;
            return retVal;
     }
    

    auto_ptr kenne ich nicht...
    Das data der Klasse will ich aber als char-Array lassen. Ich kann mir nicht vorstellen, dass es sinnvoll ist das durch string zu ersetzen.

    Ich habe noch eine andere Idee:
    Ich lasse die getChar() einfach so wie sie ist ( mit new char[num]) und erzeuge in der Klasse eine Tabelle (Array) von Zeigern, in die alle Zeiger reinkommen, die beim Aufruf von getChar() erzeugt wurden.
    Und im Destruktor mache ich dann eine Schleife, die über die Tabelle drüber läuft und alle Inhalte, auf die die Zeiger zeigen löscht.

    Dann müsste eigentlich auch alles wieder fein sauber nach der Benutzung sein..oder ?



  • fit schrieb:

    @mathik: Thx erstmal.

    //entweder (ist am einfachsten) 
     void getChar(std::string& retVal, int num);
    

    Also das will ich nicht nehmen, weil das Konzept so gedacht war, das die Ergebnisse immer als return-Wert zurück kommen sollen.

    //oder: (ist nicht sonderlich performant) 
     std::string getChar(int num);
    

    das wuerde passen, die Implementierung ist aber sicher nicht der Hit (habe vorher fast nie mit std::string gearbeitet):

    //...
    string getChar(int num){
            string retVal;
            retVal.resize(num);
            for(int i=0; i<num; ++i){
                    retVal[i] = data[pos +i];
            }
            pos +=num;
            return retVal;
     }
    

    auto_ptr kenne ich nicht...
    Das data der Klasse will ich aber als char-Array lassen. Ich kann mir nicht vorstellen, dass es sinnvoll ist das durch string zu ersetzen.

    Ich habe noch eine andere Idee:
    Ich lasse die getChar() einfach so wie sie ist ( mit new char[num]) und erzeuge in der Klasse eine Tabelle (Array) von Zeigern, in die alle Zeiger reinkommen, die beim Aufruf von getChar() erzeugt wurden.
    Und im Destruktor mache ich dann eine Schleife, die über die Tabelle drüber läuft und alle Inhalte, auf die die Zeiger zeigen löscht.

    Dann müsste eigentlich auch alles wieder fein sauber nach der Benutzung sein..oder ?

    @fit
    da ist eine ganz schlechte methode ;), nutz stattdessen den auto_ptr. hier ein linkt dazu: http://www.gotw.ca/publications/using_auto_ptr_effectively.htm

    ansonsten hat die string-klasse eine methode string::append(const char *s, size_type n);

    damit würdest du dir die schleife sparen...

    Gruß mathik



  • fit schrieb:

    @mathik: Thx erstmal.

    //entweder (ist am einfachsten) 
     void getChar(std::string& retVal, int num);
    

    Also das will ich nicht nehmen, weil das Konzept so gedacht war, das die Ergebnisse immer als return-Wert zurück kommen sollen.

    //oder: (ist nicht sonderlich performant) 
     std::string getChar(int num);
    

    das wuerde passen, die Implementierung ist aber sicher nicht der Hit (habe vorher fast nie mit std::string gearbeitet):

    //...
    string getChar(int num){
            string retVal;
            retVal.resize(num);
            for(int i=0; i<num; ++i){
                    retVal[i] = data[pos +i];
            }
            pos +=num;
            return retVal;
     }
    

    auto_ptr kenne ich nicht...
    Das data der Klasse will ich aber als char-Array lassen. Ich kann mir nicht vorstellen, dass es sinnvoll ist das durch string zu ersetzen.

    Ich habe noch eine andere Idee:
    Ich lasse die getChar() einfach so wie sie ist ( mit new char[num]) und erzeuge in der Klasse eine Tabelle (Array) von Zeigern, in die alle Zeiger reinkommen, die beim Aufruf von getChar() erzeugt wurden.
    Und im Destruktor mache ich dann eine Schleife, die über die Tabelle drüber läuft und alle Inhalte, auf die die Zeiger zeigen löscht.

    Dann müsste eigentlich auch alles wieder fein sauber nach der Benutzung sein..oder ?

    @fit
    da ist eine ganz schlechte methode ;), nutz stattdessen den auto_ptr. hier ein linkt dazu: http://www.gotw.ca/publications/using_auto_ptr_effectively.htm

    ansonsten hat die string-klasse eine methode string::append(const char *s, size_type n);

    damit würdest du dir die schleife sparen...

    Gruß mathik



  • fit schrieb:

    //oder: (ist nicht sonderlich performant) 
     std::string getChar(int num);
    

    Doch, wenn der Compiler NRVO durchführt, schon.



  • Ist das eine übliche Optimierung, oder machen das nur wenige Compiler?



  • Danke für Eure antworten.
    Habe das mit dem auto_ptr jetzt mal so probiert:

    auto_ptr<string> getString(int num){
            auto_ptr<string> retVal = new string;
            *retVal.resize(num);
            for(int i=0; i<num; ++i)
                    *retVal[i] = data[pos +i];
            pos +=num;
            return retVal;
     }
    

    Ergebnis:

    E2034 Konvertierung von 'string *' nach 'auto_ptr<string>' nicht möglich.
    

    In dem Bsp. (den Link von Dir) machen die das aber vom Prinzip her genau so, halt nur mit String:

    auto_ptr<String> f()
        {
          auto_ptr<String> result = new String;
          *result = "some value";
          cout << "some output";
          return result;  // rely on transfer of ownership;
                          // this can't throw
        }
    

    Was habe ich denn falsch gemacht ?



  • Taurin schrieb:

    Ist das eine übliche Optimierung, oder machen das nur wenige Compiler?

    g++ 3.2.2 kann es. Der Borland C++ Compiler 5.2 (von anno 1994 oder so) kann es auch, aber seltsamerweise nur, wenn man es so schreibt:

    string foo = getChar(42);

    anstatt string foo(getChar(42)); was 1 oder 2mal (je nachdem, ob es ein RVO- oder NRVO-Fall ist) den Kopierkonstruktor aufruft. Man kann wohl davon ausgehen, dass sie das inzwischen hinbekommen haben.

    Was mit MS ist, weiß ich nicht.



  • auto_ptr<string> getString(int num)
    {
            auto_ptr<string> retVal(new string);
            retVal->resize(num);
            for(int i=0; i<num; ++i)
                    (*retVal)[i] = data[pos +i];
            pos += num;
            return retVal;
    }
    

    Erstens ist der auto_ptr-Konstruktor explicit (auch wenn dein Codeschnipsel etwas anderes sagt) und zweitens musst du auf die Operatorenpräzedenz achten. Noch schöner wäre hier aber vermutlich:

    auto_ptr<string> getString(int num)
    {
            auto_ptr<string> retVal(new string(&data[pos], &data[pos + num]));
            pos += num;
            return retVal;
    }
    


  • DWORD getDWORD(void){ 
            char c[4]; 
            for(int i=0; i<4; ++i) 
                    c[i] = data[pos +i]; 
            DWORD retVal = *reinterpret_cast<DWORD*>(c); 
            pos+=4; 
            return retVal; 
     }
    

    was soll hier das kopiere? du kannst doch direkt data[pos] casten.
    und was sollen die ganzen get methoden? mach ein template. dann kann der user auch nach was parsen, was du noch nicht kanntest.


Anmelden zum Antworten