string-klasse



  • ich hab doch eine eig. string-klasse geschrieben, bloß ist die nicht stabil oder es wird irgendwelcher speicher net wieder freigegeben. ich weiß auch, wo ich ein delete einfügen müsste, bloß wenn ich das mache, stürzt er mir sofort ab... naja, werd wohl ganz auf string verzichten müssen und mich wieder char *, strcpy usw. begnügen müssen... ist für ein OS sowieso besser

    cu todo



  • ich hab doch eine eig. string-klasse geschrieben, bloß ist die nicht stabil oder es wird irgendwelcher speicher net wieder freigegeben. ich weiß auch, wo ich ein delete einfügen müsste, bloß wenn ich das mache, stürzt er mir sofort ab... naja, werd wohl ganz auf string verzichten müssen und mich wieder char *, strcpy usw. begnügen müssen... ist für ein OS sowieso besser

    Resultiert diese Schlussfolgerung aus irgendeiner Logik heraus. Wenn ja, aus welcher mir nicht bekannten?



  • Hier, das ist vielleicht keine besonders gute oder effiziente Klasse, aber sie funktioniert immerhin! 😃 Sie wurde halt von einem Anfänger geschrieben.

    [siehe späteren Beitrag]



  • Ich weis, ich hätte z.B. die substring Methode effizienter schreiben können. Ich hätte nur ein paar Zeiger inkrementieren oder auch dekrementieren brauchen und das neue Stringobjekt hätte sich den Speicher mit dem Alten teilen können. Aber ich war mir da nicht so sicher. Denn wenn das eine Objekt gelöscht wird, dürfte es Probleme geben. Und ich weis auch, dass ich die ganze Klasse hätte besser machen können und z.B. mit den beliebten template arbeiten können. Aber das ist ja alles im Konjunktiv, denn ich schreibe lieber code den ich kapiere! 😃 😉



  • Ich seh haufenweise new, aber nirgends delete. Sehr fragwürdige Empfehlung, IMHO.



  • Ach ja, habe noch was vergessen. Da diese Klasse eben noch ziemlich schlecht ist, bitte ich um Verbesserungsvorschläge! Danke!



  • Nun ja, wie man am obigen Code sieht, kann man anscheinend auch eine string-Klasse ohne Speicherverwaltung schreiben. 😃

    Du müsstest deinen Speicher schon intern verwalten. So wie du das jetzt machst übergibst du die Verantwortung dem Nutzer. Er muss Speicher vereinbaren und auch wieder löschen. Das geht auf jeden Fall schief.

    [ Dieser Beitrag wurde am 07.05.2003 um 17:49 Uhr von Braunstein editiert. ]



  • Original erstellt von Pogo:
    Ach ja, habe noch was vergessen. Da diese Klasse eben noch ziemlich schlecht ist, bitte ich um Verbesserungsvorschläge! Danke!

    Vorschlag #1: Memory-Leaks entfernen (also wie Bashar gesagt hat: auch mal deleten).
    Vorschlag #2: PreIncrement verwenden (also ++i anstatt i++) wenn PostIncrement unsinnig ist -> siehe FAQ.
    Vorschlag #3: Mal so'n paar Sachen auf den ersten Blick korrigiert

    bool String::equals(String &string) const
    {
        char* value2 = string.toCharPointer();
        char *p1 = value2, *p2 = value; // <- so besser
        bool same = true; // <- wenn du es hier schon auf true setzt sparst du dir viele Male same = true unten
        while(p1[0] != '\0' && p2[0] != '\0')
        {
            if(p1[0] == p2[0])
            {
              ++p1; // <- ++p1 ist hier schneller als p1++
              ++p2;
            }
            else
            {
              same = false;
              break;
            }
        }
        return same;
    }
    


  • Oh! Du hast recht. Stimmt, das habe ich ganz vergessen. 😃
    Naja, das lässt sich ja leicht "nachimplementieren". 😃



  • Original erstellt von Braunstein:
    Nun ja, wie man am obigen Code sieht, kann man anscheinend auch eine string-Klasse ohne Speicherverwaltung schreiben. 😃

    So ganz ohne wird das nicht gehen... 🙄
    HumeSikkins sprach ausserdem davon, dass man bei einem eigenen OS auch eine eigene Speicherverwaltung braucht...



  • Wie du an seinen Konstruktoren siehst vereinbart er keinen neuen Speicher sondern nutzt den der übergebenden Variablen.
    Siehe hier:

    String::String(char* string) {
    
        value = string;
        length = getLength(string);
    }
    

    Wenn in diesen Code nicht noch sehr viel fehlt, muss also die Speichervereinbarung und Löschung von der übergebenen Variablen übernommen werden und das bezeichne ich als schlecht designed.

    Ciao



  • String::String() {
    
        value = "NULL";
        length = 4;
    }
    

    aua



  • [cpp]
    bool String::equals(const String &string) const
    {
    char *p1 = string.toCharPointer(), *p2 = value;
    while(*p1 != '\0' && *p2 != '\0') // oder besser while(*p1&&*p2)
    {
    if(*p1 == *p2)
    {
    ++p1;
    ++p2;
    }
    else
    {
    return false;
    }
    }
    return true;
    }[/cpp]

    ich finde p[0] ist irgendwie unlogisch. es ist zwar das selbe wie *p - aber man (zumindest ich) erwartet bei p[0] doch irgendwie eine änderung von [0] und nicht vib p..

    also laufende zeiger mit *
    und über indices mit []

    man kanns auch anders herum machen, aber ich denke so ist es die gängige variante.

    ich würde nicht zweimal equals implementieren, sondern einfach:
    bool String::equals(const String &string) const { return equals(string.toCharPointer(); }
    schreiben 🙂

    du vergisst oft const zu schreiben...

    for (int i = 0; i < getLength(buffer); i++) { buffer[i] = p[c++]; c2++; }
        buffer[c2] = '\0';
    

    ein memcpy wäre besser

    und getLength(const char*) ist sowieso blödsinn - dafür gibt es strlen()

    if (endIndex > getLength() || beginIndex > getLength() || beginIndex > endIndex) return String("ERROR");
    

    blödsinn...
    ein ERROR string hat keinen sinn.
    entweder du machst n assert oder wirfst ne exception - das hier ist ein logik fehler!

    if (p[0] >= 97 && p[0] <= 122) p[0] -= 32;
    

    verwende doch tolower/toupper

    getLength(string.toCharPointer());
    

    wie wäre es mit string.getLength() ?

    du hast einige sehr verwirrende funktionen - du solltest in denen den code vielleicht kommentieren und/oder lesbarer schreiben...

    du brauchst keine statusvariablen um
    return same;
    zu schreiben zu können - du kannst ja statt same=false; einfach return false; schreiben

    du solltest keine memory leaks haben...

    und die klasse sollte den speicher selber verwalten und nicht der user

    du solltest nicht sooft den selben code schreiben - probiere eine funktion mit hilfe einer anderen zu implementieren 🙂

    das ist mir beim drüberfliegen aufgefallen



  • Shade Of Mine du vergisst das er ein eigenes os macht, klar wäre ein tolower besser aber soll er die komplete cstdlib nach programmieren?



  • Original erstellt von Dimah:
    Shade Of Mine du vergisst das er ein eigenes os macht, klar wäre ein tolower besser aber soll er die komplete cstdlib nach programmieren?

    jein.

    ein tolower/toupper braucht er sowieso!
    ein strlen auch.

    sicher muss er nicht die ganze C Library nachprogrammieren - aber die wichtigsten sachen...

    oder willst du immer wenn du tolower brauchst eine schleife machen in der du mit ascii code rumspielst?

    gerade wenn man ein OS schreibt - sollte man ordentliche bibliotheksfunktionen bereit stellen - sonst hat man doch keinen spaß daran, programme für das OS zu schreiben...



  • Original erstellt von Dimah:
    Shade Of Mine du vergisst das er ein eigenes os macht, klar wäre ein tolower besser aber soll er die komplete cstdlib nach programmieren?

    ja. nur so lassen sich auch weiterhin vernünftig programme portieren.



  • Danke für die vielen "Verbesserungsvorschläge".
    Also mal ein paar Worte zu meiner Verteidigung:

    Wie ich ja schon sagte bin ich ein Anfänger. Ich wollte einfach mal ein bisschen rumprobieren um ein bisschen Erfahrung im Umgang mit C++ zu bekommen.
    Also habe ich zu Übungszwecken alle Methoden selbst geschrieben. Ich wollte eben meine eigene Klasse ohne includes schreiben.

    So und nun ´ne Frage:

    char* str1 = "String";
    char* str2 = "...";

    Wenn ich nun

    str2 = str1;

    schreibe, was passiert dann? Wird der Wert von str1 str2 zugewiesen oder zeigt hiernach str2 einfach nur auf str1?

    Und noch eine Frage zu Refenzen:
    Also im Buch stand dass ich auf keinen Fall NULL-Referenzen fabrizieren solle.
    Aber das "darf" ich doch, so lange ich diese Referenz nicht mehr verwende ist das doch egal, oder?

    [ Dieser Beitrag wurde am 08.05.2003 um 17:25 Uhr von Pogo editiert. ]



  • Noch was:

    Was macht die Methode tolower, die ich schon in der lib finden kann?
    Gibt es da einen so großen Unterschied zu meiner Version?
    Sicherlich wird diese nicht ganz so stümperhaft wie meine sein, aber sie wird doch im Prinzip das gleiche machen, oder? Und um irgendwelche bestimmten Zeichencodes brauch eich mir ja auch keine Sorgen machen, da ja eigentlich die ersten 256 Zeichen der ganzen Zeichencodes übereinstimmen.

    @ "Shadow of Mine"

    Welche Methoden findest du verwirrend? 🙂



  • Original erstellt von Pogo:
    **@ "Shadow of Mine"

    Welche Methoden findest du verwirrend? :)**

    Shade, bitte 🙂

    zB regionMatches (viel zu lange), concat (irgendwie so viele while schleifen 😕) und replace (soviele ifs).



  • und noch was:

    String::String(char* string) {

    value = string;
    length = getLength(string);
    }

    was, wenn der pointer string nach dem aufruf dieses ctors deleted wird?? dann ist value ungültig! also muss man erst noch speicher reservieren, und zwar length+1 byte und dann strcpy&co benutzen. bei mir sähe das dann so aus:

    String::String(char* string) {
    length = getLength(string);
    value = new char[length+1]
    strcpy (value, string);
    }

    naja, wie gesagt, das einzige problem bei meiner str-klasse ist, das es speicher-lecks gibt und wenn ich das beheben will, stürzt er immer ab...
    eine eig. speicherverwaltung hab ich natürlich auch, genauso wie viele routinen der cstdlib (oft allerdings mit anderem namen, z.b. string_copy usw. (das is gerade für den anfänger noch verständlicher 🙂 (auch wenn ich mich schon eone weile nicht mehr als solchen betrachte...)

    cu todo


Anmelden zum Antworten