Menu

C++-Strings: std::string-Grundlagen, Methoden und Stolperfallen

Wie man std::string in C++ verwendet - Text sicher aufbauen, zusammenfügen, durchsuchen und zerschneiden, und warum man für echte Arbeit fast nie ein rohes char* will.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

std::string: Text, der sich selbst verwaltet

Auf der vorherigen Seite hast du gesehen, wie Smart Pointer einem Objekt erlauben, eine Ressource zu besitzen und sie automatisch aufzuräumen. std::string ist dieselbe Idee, angewendet auf Text: Er besitzt einen Puffer aus Zeichen, vergrößert ihn beim Anhängen und gibt ihn frei, wenn der String den Gültigkeitsbereich verlässt. Du rufst nie new auf, zählst nie Bytes und sorgst dich nie um einen fehlenden Nullterminator.

Um ihn zu verwenden, binde <string> ein. Die Klasse liegt im Namensraum std.

Dieser +-Operator leistet echte Arbeit - er reserviert einen neuen Puffer, der groß genug für beide Teile ist, und kopiert sie hinein. Bei einem rohen char* müsstest du zu strcpy und strcat greifen und hoffen, dass dein Puffer groß genug ist. std::string lässt diese ganze Fehlerklasse verschwinden.

Strings aufbauen und zusammenfügen

Du kannst mit + verketten, aber das Arbeitspferd, um einen String an Ort und Stelle wachsen zu lassen, ist +=. Es hängt an den bestehenden Puffer an, statt jedes Mal einen brandneuen String zu erzeugen - das ist innerhalb von Schleifen wichtig.

Eine häufige Überraschung: + braucht mindestens einen Operanden, der bereits ein std::string ist. Zwei String-Literale sind nur const char*, daher kompiliert "a" + "b" nicht - es gibt keinen operator+ für zwei rohe Zeiger. Mach zuerst einen davon zu einem String:

string s = "a" + "b";              // error: can't add two const char*
string s = string("a") + "b";      // fine - left side is a std::string
string s = "a"s + "b";             // fine in C++14+, the "s" literal suffix

Beachte, dass die letzte Form das s-Suffix aus <string> verwendet (using namespace std::string_literals;), das ein Literal direkt in einen std::string verwandelt.

In einen String hineingreifen

Ein std::string verhält sich wie ein Container aus char, du kannst ihn also indizieren, durchlaufen und nach Teilstücken fragen.

substr(pos, len) liefert einen brandneuen String, der aus dem Original kopiert wurde; es verändert die Quelle nicht. Achte auf die Grenzen: word[10] auf einem 5-Zeichen-String ist undefiniertes Verhalten - es wirft nichts, es liest einfach Datenmüll. Wenn du einen geprüften Zugriff willst, der std::out_of_range wirft, verwende word.at(10) statt word[10].

Eine weitere klassische Falle: .size() liefert einen vorzeichenlosen Typ (size_t). Eine rückwärts laufende Schleife wie for (size_t i = word.size() - 1; i >= 0; --i) endet nie, denn ein vorzeichenloses i kann nie unter null fallen - es läuft über und wird zu einer riesigen Zahl. Verwende einen vorzeichenbehafteten Index oder strukturiere die Bedingung um, wenn du einen String rückwärts durchlaufen musst.

Suchen und Ersetzen

find findet einen Teilstring oder ein Zeichen und liefert den Startindex. Ist das Ziel nicht vorhanden, liefert es die spezielle Konstante std::string::npos - vergleiche immer damit, statt anzunehmen, dass find -1 liefert.

Um Text an Ort und Stelle zu ändern, tauscht replace(pos, len, text) einen Abschnitt gegen neuen Inhalt (der eine andere Länge haben kann), und insert/erase fügen Stücke hinzu oder entfernen sie:

Strings und Zahlen

Text und Zahlen wandeln sich nicht von selbst um - "42" sind drei Zeichen, nicht die Ganzzahl 42. Die Standardbibliothek gibt dir Umwandlungsfunktionen in beide Richtungen. Verwende stoi, stod und Co., um Text in Zahlen zu parsen, und to_string für die andere Richtung.

Zwei Stolperfallen hier. Erstens wirft stoi("abc") std::invalid_argument, also sichere nicht vertrauenswürdige Eingaben mit try/catch ab. Zweitens liefert to_string(3.99) das volle 3.990000 - wenn du Kontrolle über Genauigkeit und Formatierung brauchst, ist das eine Aufgabe für String-Streams, und genau dorthin geht es als Nächstes.

try {
    int n = std::stoi(userInput);
} catch (const std::invalid_argument&) {
    std::cout << "That wasn't a number.\n";
}

Als Nächstes: Eingabe und Ausgabe

Du hast die ganze Zeit Strings mit cout ausgegeben, aber sie vom Benutzer zurückzulesen hat seine eigenen Überraschungen - cin >> name stoppt beim ersten Leerzeichen, daher braucht eine ganze Zeile wie "Ada Lovelace" stattdessen std::getline. Die nächste Seite behandelt Ein- und Ausgabe in C++ richtig: Stream-Operatoren, das Lesen ganzer Zeilen und das Mischen von >> mit getline, ohne über übrig gebliebene Zeilenumbrüche zu stolpern.

Häufig gestellte Fragen

Was ist der Unterschied zwischen std::string und char* in C++?

std::string ist eine Klasse, die ihren eigenen Speicher besitzt und verwaltet, bei Bedarf wächst und sich automatisch aufräumt. Ein char* ist nur ein roher Zeiger auf Zeichen mit einem abschließenden '\0' - du verwaltest den Puffer, die Länge und die Lebensdauer selbst. Bevorzuge std::string für fast alles; er beseitigt ganze Kategorien von Pufferüberlauf- und Dangling-Pointer-Fehlern.

Wie ermittelt man die Länge eines Strings in C++?

Rufe .size() oder den Alias .length() auf einem std::string auf: name.size() liefert die Anzahl der Zeichen als size_t. Beide liefern denselben Wert; size() ist der gängigere Stil, weil er zu allen anderen STL-Containern passt.

Wie wandelt man einen String in C++ in eine Zahl um?

Verwende std::stoi für int, std::stod für double und ähnliche (stol, stof). Beispiel: int n = std::stoi("42");. Diese Funktionen werfen std::invalid_argument, wenn der Text keine Zahl ist, also packe sie in ein try/catch, wenn die Eingabe nicht vertrauenswürdig ist.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S