Hier ist eine andere Lösung. Sie ist kompakt und einigermaßen effizient:
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
std::size_t start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
Es lässt sich leicht als Vorlage verwenden, um Stringtrennzeichen, breite Strings usw. zu verarbeiten.
Beachten Sie, dass die Aufteilung ""
ergibt eine einzige leere Zeichenkette und die Aufteilung ","
(d. h. sep) ergibt zwei leere Zeichenfolgen.
Es kann auch leicht erweitert werden, um leere Token zu überspringen:
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
std::size_t start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
if (end != start) {
tokens.push_back(text.substr(start, end - start));
}
start = end + 1;
}
if (end != start) {
tokens.push_back(text.substr(start));
}
return tokens;
}
Wenn eine Zeichenkette an mehreren Begrenzungszeichen aufgeteilt werden soll, während leere Token übersprungen werden, kann diese Version verwendet werden:
std::vector<std::string> split(const std::string& text, const std::string& delims)
{
std::vector<std::string> tokens;
std::size_t start = text.find_first_not_of(delims), end = 0;
while((end = text.find_first_of(delims, start)) != std::string::npos)
{
tokens.push_back(text.substr(start, end - start));
start = text.find_first_not_of(delims, end);
}
if(start != std::string::npos)
tokens.push_back(text.substr(start));
return tokens;
}
693 Stimmen
Kumpel... Eleganz ist in meinen Augen nur eine schicke Umschreibung für "Effizienz, die hübsch aussieht". Scheuen Sie sich nicht, C-Funktionen und schnelle Methoden zu verwenden, um etwas zu erreichen, nur weil es nicht in einer Vorlage enthalten ist ;)
19 Stimmen
while (iss) { string subs; iss >> subs; cout << "Substring: " << sub << endl; }
0 Stimmen
@nlaq, Außer, dass Sie Ihr String-Objekt mit c_str() konvertieren müssten, und wieder zurück in einen String, wenn Sie es immer noch benötigen, um eine Zeichenfolge zu sein, nicht?
28 Stimmen
@Eduardo: das ist auch falsch... Sie müssen iss zwischen dem Versuch, einen anderen Wert zu streamen und der Verwendung dieses Wertes testen, d.h..
string sub; while (iss >> sub) cout << "Substring: " << sub << '\n';
1 Stimmen
Wie wäre es mit einem String-Tokenizer: cplusplus.com/referenz/string/strtok
14 Stimmen
Verschiedene Optionen in C++, um dies standardmäßig zu tun: cplusplus.com/faq/sequenzen/strings/split
27 Stimmen
Zur Eleganz gehört mehr als nur schöne Effizienz. Zu den eleganten Attributen gehören eine geringe Zeilenzahl und eine gute Lesbarkeit. IMHO ist Eleganz nicht gleichbedeutend mit Effizienz, sondern mit Wartungsfreundlichkeit.
6 Stimmen
Die meisten Antworten hier sind auffallend lateinzentriert. Viele der Antworten gehen davon aus, dass ein einzelnes Zeichen als "Leerzeichen" verwendet werden kann, obwohl die Frage das Begrenzungszeichen als Leerzeichen definiert. Unicode hat mindestens 25 Leerzeichen. Aber die Worttrennung ist nicht nur ein Problem des Leerraums. In der Silbenschrift, wie z. B. im Tibetischen, ist die Wortabgrenzung eher ein semantisches als ein syntaktisches Problem. Daher ist die Verwendung von Leerzeichen zur Extraktion von Wörtern für viele Sprachen kein geeigneter Ansatz.
0 Stimmen
Kleiner Zusatz zum oben Gesagten. Sie können eine Gebietsschema-Facette hinzufügen, die Interpunktion als Leerzeichen behandelt, so dass Sie nicht brauchen, um das separat zu behandeln. codereview.stackexchange.com/a/57467/507
1 Stimmen
Ihr ursprünglicher Code ist eleganter als die Antworten.