Tips für weitere Funktionen in eigener String-Klasse



  • danke für die hilfe^^

    ich habe aber den realloc rausgenommen, da er überflüssig geworden ist.

    Mein Denkweg:

    Ich hatte ja am Anfang:

    void Stringclass::sc_realloc(UINT newsize)
    {
        Stringclass temp(newsize,this->data);
        myswap(temp);
    }
    
    Stringclass::Stringclass(UINT scsize, const char* c)
    :size(scsize),data(new char[size])
    {
        mycopy(c,data,size);
    }
    

    und dann noch eine funktion die dies benötigt.

    Da musste ich zuerst eine Stringclass erstellen, die wurde dann mit iorgentwelchen nicht gewollten Werten erstellt, dann übergab ich sie an sc_realloc, und schon wieder wurde eine Stringclass mit irgentwelchn Werten gefüllt, und dann erst wurde alles rüberkopiert.

    Das habe ich dann aber idiotisch gefunden, und hab erstmal sofort eine Stringclass aus der operator+ funktion erstellt mit der richtigen größe und dann kopiert. Dann würde aber trotzdem die Stringclass mit leeren Werten gefüllt werden. Also habe ich sofort das erste Array mitgegeben, und nur das 2 zweite array später reinkopiert.

    Stringclass Stringclass::operator+(const Stringclass& sc) const
    {
        Stringclass scresult(this->size+sc.size,this->data);
        mycopy(sc.data,scresult.data,sc.size,this->size);
        return scresult;
    }
    

    Somit ist der code ja schon viel kleiner geworden. Dann habe ich mir gedacht, da der Konstruktor:

    Stringclass(UINT scsize, const char* scdata);
    

    ja eigentlich nur von den Funktionen der Stringclass aufgerufen wird und am besten nicht vom Anwender, da es eine potentielle Fehlerquelle ist, aufgrund der freiwählbaren Größe, diesen Konstruktor privat zu machen. Außerdem habe ich mir einen Konstruktor hinzugefuegt, der nur ein Char-Array nimmt und dann selber die Größe erkennt, somit kann man jetzt keine Größe mehr selber eingeben.
    Somit brauche ich das sc_realloc auch nicht mehr.

    Dann dachte ich dass es aber efiizienter wäre, wenn ich im privaten Konstruktor sofort die 2 Arrays reinkopiere, so habe ich einen defaultparameter mit dem 2. Array reingebracht und das habe ich jetzt(mit der operator+ funktion)

    Stringclass::Stringclass(UINT length1, const char* scdata1,UINT length2, const char* scdata2)
    :size(length1+length2),data(new char[size])
    {
        mycopy(scdata1,data,length1);
        mycopy(scdata2,data,length2,length1);
    }
    
    Stringclass Stringclass::operator+(const Stringclass& sc) const
    {
        Stringclass scresult(this->size,this->data,sc.size,sc.data);
        return scresult;
    }
    

    Ich hätte auch den Konstruktor Stringclass(const char* c) aufrufen können, aber da der zuerst mal die Länge des Array mittels c_len(c) herausfinden musste, ist es glaube ich effizienter ihm die länge die man bereits hat mitzuteilen.

    Erreicht habe ich damit:

    -Benutzer kann nicht mehr eine Stringclass mit beliebiger größe eingeben
    -Code ist kürzer geworden(von 5 auf 2 Zeilen in den Operator+)
    -Speicher wird nicht mehr mit irgentwelchen Schrott gefüllt
    -weniger Methoden aufrüfe, vorher 4, jetzt 2 und statt 2 Konstruktore wird jetzt nur noch einer aufgerufen.

    So jetzt wollte ich euch fragen, waren meine Überlegungen ok, oder einfach nur schrott? Ist es jetzt schneller als vorherm oder...?

    Danke schonmals im Voraus

    uhsuhz



  • Hast du denn jetzt die Version bzgl. operator >> von Shade of Mine übernommen?
    Denn in deiner Version ist noch ein Fehler:

    is.getline(x,100);
    

    Du kriegst den Stream ja als Parameter übergeben und dies muß nicht unbedingt std::cin sein, sondern kann ja auch ein ifstream oder ähnliches sein.



  • ja hab ich, ist besser, nur dass ich nicht bei Leerzeichen aufhöre, sondern nur bei \n, \t und \r

    vielleicht setzte ich später alles online, damit ihr schuaen könnt^^

    noch eine Frage, reichen diese +operatoren?

    Stringclass + Stringclass
    Stringclass + Char*
    Stringclass + Char
    Char* + Stringclass
    Char + Stringclass

    dies sind die operatoren mit rückgabewert = Stringclass die ich implementieren wollte, oder fehlen noch welche?

    noch ne frage:

    bei replace, wenn ich "Test" hab und ich versuche mit replace(1,"Super") zu ersetzen, dann würde Super ja Test überschreiten, also TSuper, aber dann hab ich die buchstaben 'e' und 'r' out of range, wird da normalerweise gar nichts kopiert, oder abgeschnitten, oder string vergrößert? ich habe jetzt mal gemacht, dass return = false und nichts kopiert wird



  • uhsuhz schrieb:

    So jetzt wollte ich euch fragen, waren meine Überlegungen ok, oder einfach nur schrott? Ist es jetzt schneller als vorherm oder...?

    Ja, es ist OK so.
    Die wirklich Frage dabei ist nur, wie schnell du anhaengen willst an den String.

    Deine Variante erlaubt kein schnelles append, da du exakt soviel speicher hast wie du brauchst. std::string arbeitet zB mit mehr speicher als noetig, dafuer ist ein append ohne reallokation moeglich.

    wenn du bei deiner variante bleibst, was durchaus ok ist - solltest du es wie Java machen und einen StringBuilder anbieten der wenn ich 10 Teilstrings habe diese schnell zu einem Stringclass Objekt zusammenfuegen kann (ohne dass man 10 mal nue allokieren muss).

    operator+ ist so ok.

    bei einem replace wird normalerweise der string dann angepasst. also vergroessert bzw. verkleinert wenn die beiden suchstrings nicht gleiche laenge haben.



  • uhsuhz schrieb:

    noch eine Frage, reichen diese +operatoren?

    Stringclass + Stringclass
    Stringclass + Char*
    Stringclass + Char
    Char* + Stringclass
    Char + Stringclass

    dies sind die operatoren mit rückgabewert = Stringclass die ich implementieren wollte, oder fehlen noch welche?

    Mach statt "char*" als Parameter lieber "const char*", du willst die Zeichenkette schließlich nicht verändern und wenn ich nur einen Zeiger auf eine konstante Zeichenkette hab, soll das auch funktionieren 🙂

    Übrigens: Wenn du den Operator "StringClass + Char*" (oder auch den anderen) global definierst, also nicht in der Klasse und mit

    Stringclass operator+( const Stringclass& a, const char* b )
    

    , dann funktioniert automatisch auch "const char* + Stringclass" 😉



  • Badestrand schrieb:

    Übrigens: Wenn du den Operator "StringClass + Char*" (oder auch den anderen) global definierst, also nicht in der Klasse und mit

    Stringclass operator+( const Stringclass& a, const char* b )
    

    , dann funktioniert automatisch auch "const char* + Stringclass" 😉

    performancemaessig aber nicht ideal...



  • Inwiefern?



  • Badestrand schrieb:

    Inwiefern?

    weil dann der operator +(string,string) aufgerufen wird 🙂



  • oh hatte ich vergessen zu posten, ist natürlich alles const



  • so habs jetzt geschafft die replace-methode sauber hinzuschreiben indem ich die cut und schließlich die insert methode nehme, so wird automatisch speicher vergrößert oder verkleinert

    bool Stringclass::replace(unsigned int index, const Stringclass& sc, unsigned int length)
    {
        if(this->cut(index,length) && this->insert(index,sc,length))
            return true;
        return false;
    }
    

    @Shade of Mine

    Wie meinst du das mit dem Stringbuilder? wie kann er schneller anhängen, ich habeleider da gar keine ahnung wie ich das machen soll, vielleicht einen kleinen Denkanstoß wie das funktionnieren könnte oder eine kleine Hilfe wäre nett

    Danke , uhsuhz



  • uhsuhz schrieb:

    so habs jetzt geschafft die replace-methode sauber hinzuschreiben indem ich die cut und schließlich die insert methode nehme, so wird automatisch speicher vergrößert oder verkleinert

    bool Stringclass::replace(unsigned int index, const Stringclass& sc, unsigned int length)
    {
        if(this->cut(index,length) && this->insert(index,sc,length))
            return true;
        return false;
    }
    

    du kannst gleich
    return cut() && insert()
    schreiben.

    und bedenke halt, dass das nicht performant ist, da du 2 mal umkopieren musst. einmal fürs cut und einmal fürs insert.

    da wäre zB der StringBuilder praktisch.

    StringBuilder builder;
    builder.append(string bis zu dem gesuchten string)
    builder.append(replacement string);
    builder.append(rest des strings);
    *this = builder;
    

    der stringbuilder würde dann bei einem append nicht neu allokieren müssen da er zB immer erstmal 1024 Bytes allokiert und wenn du 1024 zeichen reinschreibst, holt er sich 2048 und danach 4096,... er allokiert also zuviel speicher - dafür hat er keine reallokationen bei append aufrufen...



  • iup danke, ich versuche dann mal einen Stringbuilder zu schreiben


Anmelden zum Antworten