C++: explode, split, tokenize

In PHP gibt es eine Funktion namens explode, die einen String anhand eines oder mehrerer Zeichen aufspaltet und als ein Array zurückgibt. Manchmal wird solch eine Funktion auch in C++ benötigt. Leider gibt es dafür keine native Implementierung. Es gibt zwar eine C-Funktion stdtok, aber die ist ziemlich unschön und gibt kein C++ Array zurück.

Im Internet findet man viele brauchbare und wenig brauchbare Beispiele für die Implementierung der explode-Funktion bzw. auch split– und tokenize-Funktionen, wie sie in anderen Sprachen genannt werden.

Ich möchte hier zwei Versionen der explode-Funktion vorstellen, die ich verwende.

Die erste Version erwartet einen Text, der aufgespalten werden soll und ein Trennzeichen. Der Text wird anhand des Trennzeichens aufgespalten und die einzelnen Teile werden am Ende als ein std::vector zurückgegeben.

std::vector<std::string> explode(const std::string& str, char delimiter) 
{
    std::vector<std::string> tokens;
    std::stringstream tokenStream(str);
    std::string tempStr;

    while(std::getline(tokenStream, tempStr, delimiter))
        tokens.push_back(tempStr);

    return tokens;
}

Die zweite Version ist etwas aufwändiger und kommt gleichzeitig mit mehreren Trennzeichen klar.

std::vector<std::string> explode(const std::string& str, 
								 const std::string& delimiters = " ") 
{
	std::vector<std::string> tokens;

	auto subStrBeginPos = str.find_first_not_of(delimiters, 0);
	auto subStrEndPos = str.find_first_of(delimiters, subStrBeginPos);

	while(std::string::npos != subStrBeginPos || std::string::npos != subStrEndPos) 
	{
		tokens.push_back(str.substr(subStrBeginPos, subStrEndPos-subStrBeginPos));

		subStrBeginPos = str.find_first_not_of(delimiters, subStrEndPos);
		subStrEndPos = str.find_first_of(delimiters, subStrBeginPos);
	}

	return tokens;
}

Die Benutzung ist in beiden Fällen kinderleicht, wie das folgende Beispiel zeigt.

#include <sstream>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
	string text = "Alle meine Entchen" 
					"schwimmen auf dem See," 
					"schwimmen auf dem See," 
					"Köpfchen in das Wasser," 
					"Schwänzchen in die Höh'.";

	cout << "Text: " << text << endl;

	cout << endl << "explode: " << endl;

	auto explodeList = explode(text, ' ');
	for(auto str : explodeList)
	{
		cout << str << endl;
	}

	cout << endl << "explode: " << endl;

	auto tokenList = explode(text, " ,");
	for(auto str : tokenList)
	{
		cout << str << endl;
	}

	cin.get();
	return 0;
}

Natürlich kann man die Funktionen so umschreiben, dass das Array als eine Referenz übergeben wird, damit zu keinen großen Geschwindigkeitsverlusten kommt, wenn man mit größeren Strings hantiert.

Viel Spaß damit! :)

Schreibe einen Kommentar