Den String in Atome zerlegen: Wie man in C++ über Wörter iteriert (und dabei nicht den Verstand verliert)
Stellen Sie sich vor: Sie schreiben einen Log-Analysator, einen Befehls-Parser oder möchten einfach nur die Wörter in einem Satz zählen. Das Erste, was einem in den Sinn kommt, ist, einen String zu nehmen und jedes Wort einzeln zu durchlaufen. In Python geht das in einer Zeile: "hello world".split(). Aber wir sind in C++, also ist Einfachheit ein Luxus, den man sich verdienen muss.
Die Frage "How do I iterate over the words of a string?" auf Stack Overflow hat Hunderttausende von Aufrufen gesammelt. Und das ist kein Zufall: Anfänger ertrinken in den Nuancen der Speicherverwaltung, während Profis nach einem Gleichgewicht zwischen Geschwindigkeit und Lesbarkeit suchen. In diesem Artikel werden wir 5 Methoden zur Iteration über Wörter in C++ untersuchen, ihre Leistung vergleichen und verstehen, wann welche verwendet werden sollte.
Wenn Sie jemals strtok geschrieben und einen Segfault erhalten haben, oder versucht haben, std::regex in eine heiße Schleife einzufügen – dieser Artikel ist für Sie.
Methode Nr. 1: Der Klassiker — std::istringstream
Die sicherste und intuitivste Methode für Anfänger. std::istringstream funktioniert wie ein Stream: Sie lesen einfach Wörter daraus, die durch Leerzeichen getrennt sind.
#include <iostream>#include <sstream>#include <string>#include <vector>
int main() { std::string text = "C++ is not for the faint of heart"; std::istringstream stream(text); std::string word; std::vector<std::string> words; while (stream >> word) { words.push_back(word); std::cout << "Word: " << word << std::endl; } std::cout << "Total words: " << words.size() << std::endl; return 0;}Vorteile: sauberer Code, keine rohen Zeiger, automatische Speicherverwaltung. Funktioniert mit beliebigen Leerzeichen-Trennzeichen (Tabulator, Zeilenumbruch).
Nachteile: langsamer als manuelle Methoden aufgrund der Stream-Erstellung. Nicht geeignet für benutzerdefinierte Trennzeichen (nur Leerzeichen).
Wann verwenden: wenn Lesbarkeit wichtiger ist als Geschwindigkeit. Ideal für Lernbeispiele und Prototypen.
Methode Nr. 2: Schnell und gefährlich — std::strtok
Ein Erbe aus C, das immer noch in der Produktion lebt. strtok modifiziert den ursprünglichen String (fügt Nullzeichen ein) und verwendet einen statischen Puffer.
#include <iostream>#include <cstring>#include <vector>
int main() { char text[] = "Fast but dangerous — handle with care"; std::vector<char*> words; char* token = std::strtok(text, " "); while (token != nullptr) { words.push_back(token); std::cout << "Word: " << token << std::endl; token = std::strtok(nullptr, " "); } std::cout << "Total words: " << words.size() << std::endl; return 0;}Vorteile: sehr schnell (arbeitet auf C-String-Ebene). Ermöglicht die Angabe eines beliebigen Satzes von Trennzeichen.
Nachteile: nicht thread-sicher, zerstört den ursprünglichen String, funktioniert nur mit char*, nicht mit std::string. Leicht undefiniertes Verhalten möglich.
Wann verwenden: nur in heißen Schleifen, in denen jede Nanosekunde zählt, und Sie sich der Single-Threading-Umgebung sicher sind. In modernem C++ besser vermeiden.
Methode Nr. 3: Manuelle Iteration — std::string::find und substr
Manchmal braucht man die volle Kontrolle. Die manuelle Iteration bietet Flexibilität und erfordert keine zusätzlichen Bibliotheken.
#include <iostream>#include <string>#include <vector>
std::vector<std::string> splitManual(const std::string& text, char delimiter = ' ') { std::vector<std::string> tokens; size_t start = 0; size_t end = text.find(delimiter);