Aufmacher News

Des Programmierers Handwerkszeug: Eine Stringklasse

Murphy
22.07.2005

Letztes Jahr war ich auf der Suche nach einer String-Klasse, die man ohne große Abhängigkeiten von Toolkits einfach in ein Projekt in C++ einhaken konnte, und die einem das Leben einfacher machen sollte. Obwohl String-Klassen eigentlich grundlegendes Handwerkszeug und Übungsaufgaben für Informatikstudenten im dritten Semester sind, konnte ich nichts finden was in Frage kam; zugleich wollte ich string aus der STL nicht verwenden.

Es läuft also darauf hinaus, dass ich mir eine eigene String-Klasse zusammenzimmerte und in den letzten Monaten immer wieder mal daran herumbastelte, bis sie die wichtigen Methoden besaß (und einige die weniger häufig benötigt werden). Diese Klasse habe ich nun veröffentlicht und würde mich über Kommentare dazu freuen.

Ähnliche Artikel

Kommentare
Neue Version
Murphy , Samstag, 20. August 2005 23:23:15
Ein/Ausklappen

Sofern es noch jemanden interessiert: Es gibt eine neue Version, in die einige der obigen Anregungen eingeflossen sind.


Bewertung: 217 Punkte bei 34 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
Re: Des Programmierers Handwerkszeug: Eine Stringklasse
Harald Nikolisin, Samstag, 23. Juli 2005 16:30:18
Ein/Ausklappen

hi murphy

was spricht gegen die STL string klasse?

gruß,
  harald




Bewertung: 270 Punkte bei 45 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Warum eine Stringklasse?
Murphy , Sonntag, 24. Juli 2005 20:28:40
Ein/Ausklappen

Sie existiert schon ;-)
Im Ernst, ich habe bei der Programmierung der Klasse den einen oder andere Kniff gelernt und endlich mal einige Konstrukte verwendet, die ich zwar aus der Theorie kannte, aber bisher im "täglichen Betrieb" nie benötigt habe. Mir gefällt das string-Interface nicht, und es fehlen einige komfortable Methoden. Man hätte zwar einen darauf basierenden Wrapper erstellen können, jedoch sind IMHO die Möglichkeiten größer wenn man die Speicherstrukturen vollständig selbst handhabt. Im Übrigen kenne ich noch erstaunlich viele Programmierer, die auch unter C++ trotz aller Probleme noch mit str[n]cpy & Co. arbeiten. Das könnte entweder Gewohnheit sein oder tieferliegende Gründe haben...


Bewertung: 244 Punkte bei 42 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Kevin Krammer, Donnerstag, 28. Juli 2005 12:39:44
Ein/Ausklappen

Im Übrigen kenne ich noch erstaunlich viele Programmierer, die auch unter C++ trotz aller Probleme noch mit str[n]cpy & Co. arbeiten

Das liegt meistens an der Benutzung veralteter Literatur beim Einstieg in C++.
Da gibt es leider tonnenweise Bücher, die irgendwo am Stand Anfang der 90er hängengeblieben sind.

Oder manchmal auch Programmierer die von C kommen und als Neuerung in C++ nur die Möglichkeit sehen, eigene Klassen zu benutzen.

Zu deiner Stringklasse:
Ist der vtable nicht bischen Overkill für eine Datenklasse?
size_t für Längen?
Gibt es den operator+= nur f+r char* und nicht für mstring?
Ein char& operator[](int pos) ist auch oft sehr fein, wenn man an bestimmte Stellen des Strings schreiben will.




Bewertung: 237 Punkte bei 39 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Murphy , Donnerstag, 28. Juli 2005 21:14:07
Ein/Ausklappen

Ist der vtable nicht bischen Overkill für eine Datenklasse? Wie meinen? Welche vtable? size_t für Längen? Hmmm, warum? Da size_t letztendlich sowieso ein unsigned int ist finde ich es so eigentlich präziser. Weiteres Beispiel: QString. Gibt es den operator+= nur f+r char* und nicht für mstring? Richtig. Ich wollte das Interface so übersichtlich wie möglich halten, deshalb habe ich nachträglich alle mit mstring& überladenen Methoden zu Gunsten von const char* und impliziter Konvertierung herausgenommen wo möglich. Sollte ich da Probleme zu erwarten haben?
Der Verzicht auf operator+(const mstring&) würde leider explizite Casts notwendig machen, deshalb habe ich ihn dringelassen. Ein char& operator[](int pos) ist auch oft sehr fein, wenn man an bestimmte Stellen des Strings schreiben will. Werde ich notieren; danke für den Hinweis. Persönlich hatte ich halt bisher nicht das Verlangen über den Indexoperator zeichenweise schreibend zuzugreifen.


Bewertung: 224 Punkte bei 34 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Kevin Krammer, Sonntag, 31. Juli 2005 18:37:10
Ein/Ausklappen

Wie meinen? Welche vtable?

Durch die virtuellen Methoden braucht eine Instanz der Klasse zusätzlich zu ihrem Datenspeicher noch Platz für die Pointer auf diese Methoden.
Üblicherweise versucht man daher Datenklassen so leicht wie möglich zu machen, also keine virtuals.

Da size_t letztendlich sowieso ein unsigned int ist finde ich es so eigentlich präziser.

Leichter an größere Größen anpassbar. Wäre zB statt time_t ein unsigned long in Benutzung, könnte man nicht einfach durch Neudefinition und Neukompilierung das Überlaufproblem korrigieren.

Natürlich ist int nicht nötigerweise 4 Byte sondern könnte auch größer sein, aber das nicht so wahrscheinlich.
size_t könnte durchaus so definiert sein, daß es Größenangaben > 4GB erlaubt.

Sollte ich da Probleme zu erwarten haben?

Ich denke nicht, aber in dem Fall würde ich eher Variante mit dem eigene Typ erwarten.
Sah für mich auf den ersten Blick ziemlich verwirrend aus, so als würde diese Variante nicht unterstützt.

IMHO ist implizite Konvertierung zwar eine nette Sache, aber kann auch zu Uneindeutigkeiten führen.
Ich würde daher den direkten Operator bevorzugen.

Persönlich hatte ich halt bisher nicht das Verlangen über den Indexoperator zeichenweise schreibend zuzugreifen.

Braucht man sicher selten, aber wenn da nicht geht, wird viel zu schnell zurück zu char* gewechselt, weil vielleicht ein ansonsten funktionierender und getesteter Code ausgetaucht werden müßte


Bewertung: 237 Punkte bei 42 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Murphy , Montag, 01. August 2005 08:57:47
Ein/Ausklappen

Üblicherweise versucht man daher Datenklassen so leicht wie möglich zu machen, also keine virtuals. Interessant; das steht anscheinend in keiner C++-Referenz.
Den Destruktor kann ich wohl problemlos nicht-virtuell machen; die beiden anderen sind aber wie die Doku erwähnt dafür gedacht für wrap() alternative Metriken bereitzustellen. Ich denke ich werde die wrap()-Funktionalität und auch die bool-Konvertierung jeweils per Define abschaltbar machen. Die Sache mit size_t muß ich mir noch überlegen; was mich daran stört ist daß man immer erst nachsehen muß wie groß diese Typen auf dem Zielsystem wirklich sind; bei den Standarddatentypen (numerisch) ist auf einen Blick erkennbar was maximal zurückkommt; ich finde es einfach "ehrlicher" bzw. unmittelbarer.

Ich würde daher den direkten Operator bevorzugen. Den müßte ich dann der Konsistenz zuliebe auch (wieder) für alle anderen Operatoren, und wohl auch für alle weiteren Methoden bereitstellen. Das hatte ich schon mal; talk about interface bloat. Ich denke ich überlasse die Arbeit dann doch lieber operator const char*, da die überladenen Methoden auch nichts anderes machten als get() aufzurufen und die const char*-Implementation zu wrappen. weil vielleicht ein ansonsten funktionierender und getesteter Code ausgetaucht werden müßte Müßte bei Ersatz von C-Stringhandling durch eine Stringklasse in existierenden Projekten sowieso, außerdem müßte alles neu getestet werden. Wenn MString überhaupt Anwender findet dann wohl eher bei Neuimplementationen, denke ich. Aber ich werd's trotzdem irgendwann einbauen, schon rein aus Neugier. Danke für deine Anregungen!




Bewertung: 244 Punkte bei 34 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Kevin Krammer, Montag, 01. August 2005 13:36:23
Ein/Ausklappen

Interessant; das steht anscheinend in keiner C++-Referenz.

Das ist eine Implikation der Sprache, die den meisten Entwicklern egal ist, weil die meistens keine Standardtypen neu implementieren.
Das trifft dann eigentlich nur Leute, die selber Container oder Basistypen implementieren um bestimmtes Verhalten zu erreichen, oder ähnliches.

Ist jetzt nicht so tragisch, man muß sich dessen aber bewußt sein, daß man durch eine einzige virtual Methode einen Overhead durch die vtable Verwaltungsstruktur in Kauf nimmt.

Nicht umsonst sind praktisch die STL Typen und Container ohne Virtuals und machen die Anpassbarkeit über Templates.

was mich daran stört ist daß man immer erst nachsehen muß wie groß diese Typen auf dem Zielsystem wirklich sind

Ansich ist das spezielle bei der Verwendung von size_t nicht nötig, weil das immer der Typ für Größenangaben ist.

bei den Standarddatentypen (numerisch) ist auf einen Blick erkennbar was maximal zurückkommt

Das ist leider noch viel abhängiger von Architektur und Compiler.
C und C++ spezifizieren keine Größen sondern praktisch nur Hierachien, also zB ein char ist mindestens 1 Byte (darf aber auch mehr sein), ein int ist nicht kleiner als ein char, ein long ist nicht kleiner als ein int, usw.

Ein 6 Bit DOS Compiler macht zb 16 Bit int, ein 32 Bit Compiler 32 Bit int.
Auf 32 Bit Plattformen ist ein long normalerweise auch nur 32 Bit, auf 64 Bit Plattformen üblicherweise 64 Bit, allerdings hab ich kürzlich gelesen, der Compiler von Microsoft würde auch auf 64 Bit nur 32 Bit longs benutzen.

Das hatte ich schon mal; talk about interface bloat

Interface Bloat ist eher so ansich feine Methoden wie replace und ähnliches, siehe std::string und dessen ziemlich minimales Interface.

Das Problem mit dem const char* Cast tritt dann voll auf, wenn die String Klasse keinen ASCII oder Latin1 Text beinhaltet sondern eine andere Kodierung.
Siehe zB QString, der intern UTF-16 benutzt und wo der const char* Cast Operator auf Latin1 konvertiert, weil das die üblichste ist.

Sicherer ist in dessen Fall die Verwendung der expliziten Konvertierungsmethoden wie zB QString::latin1() oder QString::utf8(), weil die implizite Konvertierung je nach Inhalt des Strings ein beliebig falsches Ergebnis liefern kann


Bewertung: 168 Punkte bei 40 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: Warum eine Stringklasse?
Murphy , Mittwoch, 03. August 2005 10:27:41
Ein/Ausklappen

bei der Verwendung von size_t nicht nötig, weil das immer der Typ für Größenangaben ist. Glückwunsch, jetzt hast du mich völlig verunsichert... ;-)
Ich gebe zu, size_t würde dahingehend Sinn machen weil alle relevanten C- und C++-Funktionen (new, str[n]* etc.) es benutzen und er gleichzeitig das obere Limit der handlebaren Speichergröße repräsentiert. Andererseits unterstreicht Schildt in seiner C++-Referenz (mein primäres Nachschlagewerk) immer wieder daß size_t in allen wesentlichen Sachen wie unsigned int behandelt werden kann... Ich werd's mal im Hinterkopf behalten. Interface Bloat ist eher so ansich feine Methoden wie replace und ähnliches, siehe std::string und dessen ziemlich minimales Interface. So könnte man es natürlich sehen; aber da das Ziel von MString ist eine *komfortable* Stringklasse bei der Hand zu haben, so daß man solche häufig genutzten Methoden wie replace() eben nicht immer wieder (fehleranfällig) zu implementieren braucht kann ich damit leben, denke ich. Wer minimalistisch bleiben will verwendet MString sowieso nicht... Das Problem mit dem const char* Cast tritt dann voll auf, wenn die String Klasse keinen ASCII oder Latin1 Text beinhaltet sondern eine andere Kodierung. Was bei MString kein Problem darstellt, weil keine Konvertierung erfolgt sondern der String wirklich gespeichert wird wie er übergeben wurde und sich alle Methoden auf ASCII gemäß dem aktuellen Locale beziehen. Auch setlocale() (im MString-Interface durch #define MSTRING_LOCALE zu enablen) impliziert keine Konvertierung, sondern bezieht sich lediglich auf Vergleiche und Groß-/Kleinschreibung. Sicherer ist in dessen Fall die Verwendung der expliziten Konvertierungsmethoden wie zB QString::latin1() oder QString::utf8() Sollte ich jemals eine Klasse WMString für UTF-Strings bauen werde ich das berücksichtigen (müssen).


Bewertung: 182 Punkte bei 35 Stimmen.
Den Beitrag bewerten: Gut / Schlecht

Aktuelle Fragen

Knoppix-Live-CD (8.0 LU-Edition) im Uefiboot?
Thomas Weiss, 26.04.2017 20:38, 0 Antworten
Hallo, Da mein Rechner unter Windows 8.1/64Bit ein Soundproblem hat und ich abklären wollte, o...
Grub2 reparieren
Brain Stuff, 26.04.2017 02:04, 5 Antworten
Ein Windows Update hat mir Grub zerschossen ... der Computer startet nicht mehr mit Grub, sondern...
Linux open suse 2,8
Wolfgang Gerhard Zeidler, 18.04.2017 09:17, 2 Antworten
Hallo.bitte um Hilfe bei. Code fuer den Rescue-login open suse2.8 Mfg Yvo
grep und sed , gleicher Regulärer Ausdruck , sed mit falschem Ergebnis.
Josef Federl, 15.04.2017 00:23, 1 Antworten
Daten: dlfkjgkldgjldfgl55.55klsdjfl jfjfjfj8.22fdgddfg {"id":"1","name":"Phase L1","unit":"A",...
IP Cams aufzeichnen?
Bibliothek der Technischen Hochschule Mittelhessen / Giessen, 07.04.2017 09:25, 7 Antworten
Hallo, da nun des öfteren bei uns in der Nachbarschaft eingebrochen wird, würde ich gern mein...