C++ C++: String Trennung

TuxuT

Ensign
Registriert
Sep. 2011
Beiträge
251
Hallo Gemeinde.
Ich bräuchte einen eleganten Ansatz für folgendes Problem:

Gegeben sei folgender String
std::string my_string = " "string1,test", "string2,test" , "string3,test" , "string4,,test", "string5,,,test" "

Okay, jetzt möchte ich die 5 Strings in my_string gerne aufteilen. Und zwar sind diese kommagetrennt und von "" umkreist, damit man auch innerhalb der Teilstrings Kommas verwenden kann. Zwischen den Trennungskommas können auch Leerzeichen sein wie oben zu sehen, die müssen natürlich ignoriert werden.

Als Ziel sollten also die Teilstrings z.B. in einen std::vector <std::string> vTargetString abgelegt werden (ohne die umkreisenden "").

vTargetString[0] = "string1,test"
vTargetString[1] = "string2,test"
vTargetString[2] = "string3,test"
vTargetString[2] = "string4,,test"
vTargetString[2] = "string5,,,test"

Vielen Dank schon mal für eure Unterstützung.
 
Mein C++ ist etwas eingerostet, aber ich würde mir an deiner Stelle Reguläre Ausdrücke (regex) anschauen.
Du suchst quasi nach "(\w+,+\w+)", also allen alphanumerischen Wörtern, die in Anführungszeichen stehen und durch mindestens 1 Komma getrennt sind. Durch die Klammern wird der Teil zwischen den Anführungszeichen als Gruppe ansprechbar. Die Gruppen kannst du dann in deinen Vector oder was auch immer übernehmen.

Den genauen Befehl kannst du dir ja aus der Referenz raussuchen:
http://www.cplusplus.com/reference/regex/

Hoffe das hilft dir schon weiter.
 
Du kannst den ganzen String auch einfach nach Anführungszeichen splitten und anschließend alles verwerfen, was nach einem Trim nur noch ein "," ist.
 
TuxuT schrieb:
Ich bräuchte einen eleganten Ansatz für folgendes Problem:

Schau mal, ob das <regex> von Deinem Compiler folgendes kann:
Code:
#include <iostream>
#include <regex>
#include <string>
using namespace std;

...
...
 string s = "\"string1,test\", \"string2,test\",\"string3,test\","
            "\"string4,,test\",\"string5,,,test\"";
 vector<string>vTargetString;

 regex  r("\"([^\"]+)\"");
 smatch m;
 while (regex_search(s, m, r)) {
    vTargetString.push_back(m[1]);
    s = m.suffix();
 }
...
Meiner kann (Visual C++ 2015).
 
Viele Wege führen zum Ziel .. ich würds mit standard-Funktionen machen:
find und substr
Oder zu fuß irgendwie (ungetestet) so:
Code:
// First: Find all positions of "
std::vector<size_t> posOfQuote;
for (size_t i = 0; i < myString.size(); ++i)
{
  if (myString[i] == '"')
    posOfQuote.push_back(i);
}
assert(posOfQuote.size() % 2 == 0); // alternativ if (posOfQuote.size() %2 != 0) return;
// Second: Extract all substrings and store them in a new vector
std::vector<std::string> subStrings;
for (size_t i = 0; i < posOfQuote.size(); i += 2)
{
  size_t lengthOfSubstring = posOfQuote[i+1] - posOfQuote[i];
  subStrings.push_back(myString.substr(posOfQuote[i], lengthOfSubstring));
}
 
Zuletzt bearbeitet:
[QUOTEIch bräuchte einen eleganten Ansatz für folgendes Problem:[/QUOTE]
Elegant wird schwierig.
'n sehr schönes Beispiel dafür um zu zeigen, wie ungeeignet C++ für solche Sachen ist. Weils nur umständlich zu lösen ist.

In irgendeiner Skriptsprachen wär das ein Zweizeiler. Erklärt aber auch die vielen millions lines of code C++ Projekte ;)
 
Was ist an der Lösung von blöderidiot denn nicht elegant?

​Zeig uns doch mal nen 2-Zeiler in LUA, der das selbe macht, aber tdm noch elegant ist. (Den Code von blöderidiot kannst du auch in eine Zeile schreiben)
 
'n sehr schönes Beispiel dafür um zu zeigen, wie ungeeignet C++ für solche Sachen ist. Weils nur umständlich zu lösen ist.
Dem will ich natürlich nicht generell widersprechen aber das "nur" stört mich. Ich bin auch immer wieder froh, wenn ich mal was in Python mache aber es ist auch in C++ eine Frage des Weges den man wählt. Ich wollts in diesem Thread nicht schon wieder sagen aber Qt ist eine ganz tolle C++ Erweiterung die einem viel Arbeit abnimmt. Damit wird 'selbst C++' sehr angenehm ;)
C++ ist nunmal eine Sprache die selbst auf sehr kleinen µCs ohne OS funktioniert die aber eben auch zu einer sehr komfortablen Sprache erweitert werden kann.
zB mit QString split erhält man in nur einer Zeile direkt die substrings in einer Art vector.
Alternativ auch QString splitRef um Kopien zu vermeiden und gerade bei 'sehr großen' Strings sehr schnell und wahrscheinlich signifikant schneller als jede Skriptsprache. Strings könnten ja zB auch gigabyte an Protein/DNA krams sein .. da will man evtl nicht zigmal kopieren.
Durch QString und dem regex von blöderidiot ist es dann sogar nur eine gut lesbare Zeile bzw ein Befehl:
Code:
QStringList subStrings = myString.split(QRegExp("\"([^\"]+)\""), QString::SkipEmptyParts);
 
Zuletzt bearbeitet:
kuddlmuddl schrieb:
Ich will dem natürlich nicht widersprechen und bin auch immer wieder froh, wenn ich mal was in Python mache aber es ist auch in C++ eine Frage des Weges den man wählt.
In der Tat. Gerade bei C++ ist ja die Spanne recht groß zwischen dem, was (ich sags jetzt mal so) modernes C++ ausmacht bis hin zu irgendwelchen finsteren Hacks die dann noch ausgiebig die C-Kompatbilität auskosten. :-)

Ansonsten ist Python für solche Sachen ganz nett, wobei ich selbst mich ja wieder von Python verabschiedet hab bzw. nur noch da nutze, wo es unumgänglich ist wie bei Blender 3D. Besonders in der Anfangszeit fand ich das mit den semantischen Whitespaces nervig. Man hat irgend ein Stück Code aus dem Internet kopiert und angepasst und es lief nicht, weil irgendwo ein Leerzeichen zuviel war oder ein Tab statt einem Leerzeichen.
Ok. Damit kann man aber noch leben (vor allem wenn man nen passenden Editor nimmt). Aber manchmal will man (bzw. ich) auch statische Typprüfung und dergleichen und ich will auch meine Variablen ordentlich deklarieren, damit ich nicht irgendwo ein Tippfehler hab der einem dann erst zur Laufzeit auf die Füße fällt.

Schlussendlich bin ich dann bei Racket gelandet, einem Lisp/Scheme-Dialekt. Auch das Makrosystem finde ich sehr ansprechend und sowieso hat man ne schöne Sprachspielbox.
Da die Lisp-Syntax aber nicht jedermanns Sache ist (ums vorsichtig auszudrücken) und Python eben verbreiteter ist und für vieles gut genug, sag ich dann oft auch "wenns geht, nimm Python".

Vor allem hat Python diesen großen Vorteil das Du für alles und jeden Bibliotheken hast. Das macht Python so interessant. Hoher Abstraktionslevel bei sehr viel Support ... in jeglicher Hinsicht.


kuddlmuddl schrieb:
Ich wollts in diesem Thread nicht schon wieder sagen aber Qt ist eine ganz tolle C++ Erweiterung
Hehe. Ja. QT hat bei C++ so ein bisschen die Rolle wie der Joker bei "Wer wird Millionär". :-)

kuddlmuddl schrieb:
ist es dann sogar nur eine gut lesbare Zeile bzw ein Befehl:
[...]
Ja. Das kommt dem, was ich vor meinem geistigen Auge hatte, erheblich näher. :-)



kuddlmuddl schrieb:
um Kopien zu vermeiden und gerade bei 'sehr großen' Strings sehr schnell und wahrscheinlich signifikant schneller als jede Skriptsprache.
Ja. Das kann ich mir gut vorstellen.
Apropos Geschwindigkeit. Da fällt mir auch noch ein Minuspunkt zu Python ein. Das kann ja echt extrem langsam sein und dann noch gepaart mit einem GIL kommt da manchmal richtig Freude auf.

Ansonsten. Klar, C++ bleibt da interessant, wo man wirklich Geschwindigkeit braucht. Wobei ich hier Rust als interessanten Kandidaten sehe, im C++ Bereich zu "wildern".

Native-Code, keine Garbage Collection und mit Sicherheit im Hinterkopf designed, so dass man sich erstmal nicht versehentlich so leicht in den Fuß schießen kann. Für "Drecksarbeit" kann man sich ein unsafe-Bereich deklarieren.
Insgesamt sieht das alles ganz interessant aus. Und Mozilla selbst verwendet schon teilweise Rust-Code im Firefox und mit der neuen Engine Quantum wirds dann noch mal deutlich mehr. Das ist dann auch mal ein schönes real-world Experiment, inwieweit das zu sichereren aber dennoch schnellen Code führt.

Es bleibt also weiter spannend. :-)
 

Ähnliche Themen

Antworten
7
Aufrufe
1.306
Zurück
Oben