C++ Kurs

String Objekte I

Die Themen:

string-Klasse

Für die Bearbeitung von Strings stellt die C++ Standard-Bibliothek die Klasse string zur Verfügung. In den nachfolgenden Kapiteln werden für die Bearbeitung von Strings hauptsächlich nur noch Objekte dieser Klasse verwendet und keine C-Strings.

Sehen wir uns zunächst einmal an, was die string Klasse so interessant macht:

  1. Es wird automatisch genügend Speicher reserviert, um eine vorgegebene Zeichenfolge ablegen zu können. Und allein dies ist schon ausreichend Grund genug, die string Klasse einzusetzen.
  2. Es stehen diverse Operatoren zur Verfügung, um Strings auf einfache Art und Weise bearbeiten zu können. So fügt zum Beispiel der Operator + zwei Strings zusammen.
  3. Es stehen Konvertierungen zur Verfügung um ein string Objekt in einen char* und umgekehrt zu konvertieren.

Die Klasse string enthält noch wesentlich mehr Eigenschaften als in dieser kurzen Einführung aufgezeigt werden kann. In einem späteren Kapitel werden wir uns deshalb die Klasse string nochmals etwas genauer ansehen.

Wenn die Klasse string in einem Programm eingesetzt werden soll, so muss mittels #include <string> die dazugehörige Header-Datei eingebunden werden. Dabei ist aber unbedingt darauf zu achten, dass hier kein .h steht! Die Header-Datei string.h ist eine völlig andere Header-Datei!

Ferner ist zu beachten, dass die Klasse string im Namensraum std definiert ist, d.h. bei der Definition eines Strings muss entweder std::string oder aber vorher die Anweisung using std::string; stehen.

Sehen wir uns nun einmal an, wie string Objekte definierte werden.

Hinweis

Sollten Sie mit dem Begriff Objekt im Augenblick noch etwas Schwierigkeiten haben, so stellen Sie sich unter einem Objekt in erster Näherung einfach eine Variable vor, welche zusätzlich noch Funktionen zur Verfügung stellt um den Inhalt der Variable zu bearbeiten.

Noch einmal zur Erinnerung: Damit in Zukunft nicht die völlige Verwirrung bezüglich des Begriffs String auftritt, wird im weiteren Verlaufe des Kurses unter einem String immer ein string Objekt verstanden. Zeichenfolgen die in char-Feldern abgelegt sind (das sind diejenigen, die mit einer binären 0 abgeschlossen sind), werden dagegen als C-String bezeichnet, da dies unter C die einzige Möglichkeit war, veränderbare Zeichenfolgen abzulegen. Daraus folgt unter anderem, dass ein char-Zeiger zwar auf einen C-String zeigen kann, aber niemals auf einen String.

Strings definieren

Im Prinzip wird ein String genauso definiert wie z.B. eine short-Variable, nur dass anstelle des Datentyps short nun der Datentyp string steht. Ein so definierter String enthält noch keine Zeichen, d.h. er ist leer.

Ein String kann bei seiner Definition aber auch bereits mit einer Zeichenfolge initialisiert werden. Diese Initialisierung erfolgt prinzipiell gleich wie die Initialisierung einer beliebigen anderen Variable, d.h. nach dem Stringnamen folgt der Zuweisungsoperator und danach die Zeichenfolge, mit der der String initialisiert werden soll. Diese Zeichenfolge kann entweder ein C-String Literal, eine C-String Konstante oder aber auch ein Zeiger auf ein char-Feld sein, in dem ein entsprechender C-String abgelegt ist. Desweiteren kann String mit einem bereits bestehenden String bei seiner Definition initialisiert werden, d.h. es wird eine String-Kopie erstellt.

Und selbstverständlich können auch String-Felder definiert werden. Hierbei ist zu beachten, dass das Feld dann n Strings aufnimmt, welche auch unterschiedliche Längen besitzen können. Dies darf nicht mit der Definition eines char-Feldes verwechselt werden, das ja einen C-String mit maximal n-1 Zeichen aufnehmen kann.

PgmHeader
// Header-Datei für string einbinden
#include <string>
using std::string;

// Leeren String definieren
string empty;
// String mit C-String initialisieren
string text1 = "Ein String";
// String Feld definieren
string array[10];
// und erstem String einen C-String zuweisen
array[0] = "String-Element 0";
// String mit einem anderen String initialisieren
string text2(text1);

War bis hier her nicht so kompliziert, oder? Zugegeben, wir haben uns nur die einfachen Fälle angesehen wie ein String erstellt werden kann. Die C++ Standard-Bibliothek kennt noch weitere Methoden ein string Objekt zu erstellen. Für unsere Zwecke sollten diese Möglichkeiten aber ausreichen. Mehr Infos finden Sie, wie immer, in der Online-Hilfe zur Klasse string.

Ein- und Ausgabe von Strings

Fangen wir mit dem einfachen Fall an, der Ausgabe von Strings.

Die Ausgabe eines Strings unterscheidet sich nicht von der Ausgabe anderer Daten, d.h. der String kann direkt in den Ausgabestream einfügt werden.

PgmHeader
#include <iostream>
#include <string>
using namespace std;

int main()
{
   string text = "Ein string-Objekt";
   cout << text << endl;
}

Beim Einlesen eines Strings muss jedoch unterschieden werden, ob die einzelnen Wörter einer Eingabe in mehreren Strings abgelegt werden sollen oder die gesamte Eingabezeile in einem String.

Um die Wörter einer Eingabe in einzelne Strings abzulegen, werden die Strings nacheinander im Eingabestream angegeben. Und hier ist auch gleich einer der Vorteile von Strings zu sehen: unabhängig davon, ob ein Wort aus 4 Zeichen oder 80 Zeichen besteht, es wird automatisch genügend Speicher reserviert um das Wort im String ablegen zu können.

PgmHeader
#include <iostream>
#include <string>
using namespace std;

int main()
{
   string word1, word2;
   cin >> word1 >> word2;
}

Soll dagegen eine ganze Zeile in einem String abgelegt werden, so ist hierfür die Funktion getline(...) zu verwenden.

PgmHeader
#include <iostream>
#include <string>
using namespace std;

int main()
{
   string line;
   getline(cin,line);
}

Beachten Sie bitte, dass die hier verwendete Funktion getline(...) eine andere Signatur (Anzahl und Typ der Parameter) besitzt, als die Memberfunktion getline(...) des Eingabestreams cin. Die hier verwendete Funktion getline(...) enthält im ersten Parameter eine Referenz auf den Stream, von dem die Zeile eingelesen werden soll. Im Beispiel ist dies der Eingabestream cin. Ebenso möglich wäre hier z.B. auch die Angabe eines Dateistreams vom Typ ifstream. Der zweite Parameter ist dann eine Referenz auf das string Objekt, in dem die Eingabe abgelegt wird. Und nochmals: ganz gleich wie lange die Eingabezeile ist, es wird immer genügend Speicher reserviert um die komplette Zeile im String ablegen zu können.

String-Operationen

Zuweisungen

Die einfachste Operation ist die Zuweisung. Damit kann einem String ein C-String Literal, eine C-String Konstante oder auch ein anderer String zugewiesen werden.

PgmHeader
// Zwei Strings definieren
string s1, s2;
// C-String-Literal einem String zuweisen
s1 = "Dies ist String1";
// String einem anderen String zuweisen
s2 = s1;

Addition

Ebenso ist es möglich, Strings einfach mit Hilfe des Operators + zu 'addieren', d.h. aneinander zu hängen. Zusätzlich zum Operator + stellt die Klasse string zur Addition noch den Operator += zur Verfügung.

PgmHeader
// Zwei Strings definieren
string s1("Text1"), s2;
// C-String-Literal addieren, s1 danach "Text1 erweitert"
s1 += " erweitert";
// Strings addieren, s2 danach "Text1 erweitert in s2"
s2 = s1 + " in s2";

Zeichen-Zugriff und Stringlänge

Um auf einzelne Zeichen innerhalb eines Strings zuzugreifen, wird, wie bei den C-Strings, der Indexoperator [] eingesetzt. Auch hier hat das erste Zeichen im String den Index 0. Soll der gesamte String durchlaufen werden, so liefert die Memberfunktion size() hierfür die Anzahl der Zeichen im String. Noch einfacher geht es aber mit der range-for Schleife um den kompletten String sequentiell zu durchlaufen.

PgmHeader
// String definieren und initialisieren
string s1("Ein Text");
// Alle Zeichem im String einzeln ausgeben
for (auto i=0; i<s1.size(); i++)
   cout << s1[i] << ',';
// Zugriff mittels range-for
for (auto zeichen: s1)
   cout << zeichen << ',';

Strings vergleichen

Strings können mit den bekannten Vergleichsoperatoren <, >, == usw. verglichen werden. Der Vergleich erfolgt hierbei lexikalisch, d.h. 'Aaaa' ist kleiner als 'Bb'. Bei einem der beiden Operanden des Vergleichsoperators kann anstelle eines string Objekts auch ein const char* Zeiger angegeben werden.

PgmHeader
// Zwei String definieren und initialisieren
string s1("Aaaa"), s2("Bb");
// Strings vergleichen
if (s1 < s2)
   cout << "s1 kommt vor s2" << endl;
else
   cout << "s2 kommt vor s1" << endl;

char-Zeiger Konvertierung

Um einen String in einen const char-Zeiger zu konvertieren, besitzt die string Klasse die Memberfunktion c_str(). Mit Hilfe dieser Konvertierung kann dann überall dort ein String verwendet werden, wo ansonsten ein const char-Zeiger benötigt wird. Im Beispiel wird damit der Inhalt eines Strings in ein char-Feld kopiert.

PgmHeader
// String definieren und initialisieren
string s1("Ein Text");
// char Feld definieren
char charArray[40];
// Zeichen aus String in char-Feld umkopieren
strcpy(charArray,s1.c_str());

Der umgekehrte Weg, also einen char-Zeiger in ein String zu konvertieren, erfolgt über den am Anfang dieses Kapitels aufgeführten Zuweisungsoperator. Beachten Sie, dass die Memberfunktion c_str() einen const char* liefert und somit der Inhalt des Strings nicht über diesen Zeiger verändert werden kann.

Damit wollen wir an dieser Stelle die Einführung des string Datentyps abschließen. Der string Datentyp enthält, wie bereits erwähnt, noch zahlreiche weitere Memberfunktionen, um z.B. Zeichen mitten im String einzufügen oder zu löschen oder sogar Zeichenfolgen in einem String zu suchen. Diese Memberfunktionen werden wir uns später in einem weiteren Kapitel noch ansehen.

Beispiel und ÜbungUnd hier geht's zum Beispiel und zur Übung.