String Seperator Funkton - Feedback
-
Hallöchen zusammen,
ich bin mal von riesigen, unrealisierbaren Projekten weggegangen und hab mal was kleines programmiert. Das Programm soll mehrere Strings, die alle durch einen bestimmten char getrennt werden, einzeln ausfischen können.
Bsp: "Hallo wie gehts?"
char: ' 'Hallo wie gehts?
Bsp.: "seperated*by*asterisks"
char: '*'seperated by asterisks
meine Funktion dafür sieht so aus:
std::vector<std::string> seperateString(std::string str, char seperator) { std::vector<std::string> seperatedStrings; std::string partString(""); for (unsigned i = 0; i != str.size(); ++i) { if (str[i] != seperator) { partString += str[i]; } else { seperatedStrings.push_back(partString); partString = ""; } } return seperatedStrings; }
Meine Frage: Wie hättet ihr das Problem gelöst? Gibt es da bessere Möglichkeiten, habe ich vielleicht potenzielle Fehler nicht behandelt? Ist am Code-Stil etwas Verbesserungsdürftig?
Über Feedback würde ich mich sehr freuen
mfg
HarteWare
-
Bei dir fehlt noch der letzt Teil des strings.
"Hallo wie gehts?" "Hallo" "wie"
Das "gehts?" fehlt.
Außerdem wäre es praktisch leere strings gleich wegzulassen.
Ich hätte das jetzt so gemacht, ist die einfachste Methode einfach die Standardlib zu nutzen:std::vector<std::string> splitString(std::string str, char seperator, bool allowEmpty) { std::vector<std::string> result; std::string token; std::stringstream stream(str); while(std::getline(stream, token, seperator)) { if(allowEmpty || token.size() > 0) result.push_back(token); } return result; }
-
Achja, stimmt, in main hatte ich dann so etwas, was aber nicht das Problem löst, sondern nur ein ekliger "hack" ist:
if (input[input.size() - 1] != seperator) { input += seperator; // else last word is lost }
Dass es ein getline mit delimiter als 3. Argument gibt wusste ich garnicht... (dann wird wohl '\n' der default sein?)
Ist natürlich viel einfacher... Genau wegen solchen Dingen frage ich eben.Vielen Dank für die Rückmeldung
mfg
HarteWare
-
Ich hätte jetzt das Interface so gemacht, dass man auch ohne dynamischen Speicher auskommen kann. Die Ausgabe hätte ich in einen Iterator gemacht.
template <typename Iter, typename SplitT, typename OutputIter, typename OutputT = std::iterator_traits<OutputIter>::value_type> OutputIter split_range(Iter first, Iter last, SplitT split, OutputIter out) { ... // Wenn was gefunden ist: *out++ = OutputT(from, to) } // Benutzung: std::vector<string> split; split_range(begin(str), end(str), ' ', std::back_inserter(split)); // Hier keine dynamische Allozierung nötig. std::array<std::pair<std::string::const_iterator, std::string::const_iterator>, 100> split2; split_range(begin(str), end(str), ' ', split2.begin());
-
nette lösung, fast but unreadable, aber obskur.
OP, statt dem ständigen += würde ich die separatoren einmal vorher zählen und den vektor einmal per reserve vergrößern um neuallokierungen zu sparen.