Lernziele
Die Klasse string |
| Anlegen, Kopieren, Abändern und Verketten von Strings |
| Zugriff auf Substrings |
„Am Anfang war das Wort und das Wort bei Gott und
Gott war das Wort.“. Es ist schon eine biblische
Weisheit, dass Worte etwas ungeheuer Wichtiges sind. Beginnen
wir daher mit dem Datentyp von LEDA, der zum Speichern und
Verarbeiten von Worten und Sätzen nützlich ist, dem Typ
string, einem der einfachsten Datentypen von LEDA.
Ein String ist eine
Zeichenkette, d. h. eine Folge von mehreren (oder auch gar keinem)
Zeichen. Der LEDA-Typ string ist somit eng mit dem C++-Typ
char[] verwandt, besitzt gegenüber diesem jedoch eine
Reihe von Vorteilen, die wir gleich kennen lernen werden.
Wir wollen diesen Typ zunächst dazu benutzen, ein bisschen mit Worten zu spielen. Viele weitere Beispiele dieses Tutoriums sind Spiele mit Wörtern und Sätzen. Mit ihnen können komplexe Sachverhalte oftmals auf anschauliche und belustigende Weise dargestellt werden.
RETSINAKANISTER. Wie bitte? Der Autor ist von der Komplexität der Sprache C++ frustriert und möchte sich betrinken?[4] Nein, er hat ein Wort gebildet, das vorwärts wie rückwärts gelesen gleich ist! Ein solches Wort heißt Palindrom. Vernachlässigen wir dabei Leerzeichen, Satzzeichen und Groß-/Kleinschreibung, so können wir die Definition auf ganze Sätze ausdehnen. Einige berühmte Satzpalindrome sind „Ein Neger mit Gazette zagt im Regen nie“, „Nie grub Ramses Marburg ein“ oder der englische Satz „A man, a plan, a canal - Panama“.
Schreiben wir zunächst ein LEDA-Programm, das einen String von der Standardeingabe liest und testet, ob dieser ein Palindrom ist. Dazu erzeugt das Programm aus dem Eingabestring den umgedrehten String (d. h. den String mit umgekehrter Reihenfolge der einzelnen Zeichen) und vergleicht ihn mit dem ursprünglichen. Um den String umzudrehen, hängt es nacheinander alle Zeichen von hinten nach vorne an einen zweiten String an. Dieses Programm offenbart schon recht viele Eigenschaften von LEDA im Allgemeinen und LEDA-Strings im Besonderen.
#include <LEDA/string.h>
#include <iostream>
using leda::string;
using std::cout;
int main() {
string s; // default initialization
s.read_line();
string r;
for(int i = s.length() - 1 ; i >= 0 ; i--)
r += s[i]; // inefficient, see below!
if(s == r) // fast comparison of handle-like type
cout << s << " is a palindrome\n";
else
cout << s << " is not a palindrome\n";
}
Hier wird zunächst der String
s mit Default-Initialisierung definiert,
d. h., bei der Definition wird die Variable auf den Default-Wert
des Datentyps[5] gesetzt. Das ist typischerweise der
„einfachste“ Wert des Typs; bei Strings ist das der
Leerstring, d. h. der String, der aus keinem Zeichen
besteht.
Strings bieten eine große Anzahl von Operationen an.[6] Über die Methode
s.read_line();
kann ein String s von der
Standardeingabe gelesen werden. Dabei dient das
Zeilentrennzeichen \n als Endmarkierung einer
Zeile.
Das obige Programm hängt durch Verwenden des Operators
+= das jeweils nächste Zeichen des Strings
s an den String r an. Allgemein kann durch
r += s;
ein String s an den String r angehängt werden. Der Operator +=
liefert dabei eine Referenz auf r zurück.
Auf
die einzelnen Zeichen eines Strings wird dabei durch den
Subskript-Operator [] zugegriffen:
char& c = s[i];
Er liefert eine Referenz auf das i-te Zeichen zurück, so dass über ihn dieses Zeichen auch abgeändert werden kann.
Der Vergleichsoperator
s == r;
vergleicht zwei
Strings s und r miteinander.
Im Vergleich zum Typ char[] von C++ fällt
auf, dass wir uns hier nicht um Allokation von Speicherplatz
kümmern müssen. Der String r wird durch den
Operator += auf magische Weise länger und
länger.
[4] Ja, C++ ist manchmal frustrierend. Der Autor hat in
diesem Tutorium versucht, nur Basiskonzepte dieser mächtigen
Programmiersprache zu verwenden. Der Schwerpunkt liegt auf der
Beschreibung der Typen und Algorithmen von LEDA, und daher
bestehen die meisten Programme aus einem einzigen
main().
[5] Falls es einen solchen
gibt. Die eingebauten C++-Typen wie char,
int oder double haben keinen
Default-Wert und auch einige Typen von LEDA
nicht.
[6] Wir müssen hier allerdings zugeben, dass
LEDA-Strings nicht so mächtig sind wie die entsprechenden
Datentypen auf Stringbehandlung spezialisierter Sprachen wie
Perl und AWK. Einem Vergleich mit der gleichnamigen Klasse
string aus der C++-Standardbibliothek
halten sie aber stand; die beiden Klassen besitzen nahezu dieselbe Funktionalität.