Strings splitten
-
Ich glaube TStringList besitzt die Eigenschaften "DelimitedText" und "Delimiter", die das für dich tun.
-
Oder ne Funktion die eine neue TStringList zurückgibt...übergibst die
unformartierte und bekommst deine nach Wunsch formatierte
zurück.
Innerhalb der Funktion zwischen 2 Tab ausschneiden,
die einzelnen Werte in eine Stringliste packen und zurückgeben.
Oder übergibst einen Zeiger auf die unformatierte und
rückst sie dir zurecht.Delimiter bzw. DelimitedText kann man ruhig verwenden
wenn man nicht selber parsen möchte.Der Gedanke mit der STL war blödsinn. Du verwendest
ja TStrings
-
rudpower schrieb:
Toll wäre eine Methode, die als Parameter das Trennzeichen (hier den Tabulator) erwartet und mir die einzelnen Strings zurückgibt.
http://docwiki.embarcadero.com/Libraries/de/System.StrUtils.SplitString
-
erst mal vielen Dank für die schnellen Antworten.
Wenn ich in der Borland Hilfe schau hat weder TStringList noch TStrings die Eigenschaft "DelimitedText" oder "Delimiter". Evtl. liegt es daran das ich mit dem Borland Builder Version 5 arbeite?
http://docwiki.embarcadero.com/Libraries/de/System.StrUtils.SplitString
Wie inkludiere ich die Methode SplitString? Lässt sich das mit meiner Borlandversion machen?
-
rudpower schrieb:
Wenn ich in der Borland Hilfe schau hat weder TStringList noch TStrings die Eigenschaft "DelimitedText" oder "Delimiter". Evtl. liegt es daran das ich mit dem Borland Builder Version 5 arbeite?
Ja, kann. Viele Grüße ins letzte Jahrhundert.
rudpower schrieb:
http://docwiki.embarcadero.com/Libraries/de/System.StrUtils.SplitString
Wie inkludiere ich die Methode SplitString?
Du schaust auf der Doku-Seite nach, in welcher Unit die Funktion lebt, und dann überlegst du dir, wie wohl die dazugehörige Headerdatei heißen müßte.
Tip: In C++Builder vor XE2 hatten die Unit-Namen noch keine Pseudo-Namespaces, d.h. statt z.B. "System.Classes" hieß das Unit nur "Classes".
rudpower schrieb:
Lässt sich das mit meiner Borlandversion machen?
Keine Ahnung. Wenn nicht, mußt du dir halt selber eine SplitString()-Funktion bauen.
-
Hier würde ich eine STL-Variante bevorzugen. Das geht ganz einfach mittels stringstreams.
AnsiString zahlen; // in diesen String kommen die Zahlen wie oben gezeigt. std::stringstream str(zahlen.c_str()); // alles in den Stringstream übertragen double zahl; for( unsigned int i=0; i<3; ++i) { str >> zahl; } // jetzt steht der 3. Wert in zahl
-
Du könntest aus dem String deiner Stringliste auch wieder eine Stringliste machen:
TStringList *TrennList = new (TStringList); AnsiString ASTrenn = "25,99/t589,87/t-45,5678/t34,57854"; ASTrenn = Ersetzen (ASTrenn, "\t", "\n"); //Tab durch Zeilenumbruch ersetzen TrennList->Text = ASTrenn;
TrennList->Count liefert dir dann gleich die Anzahl der Elemente.
Auf die einzelnen Elemente der TrennList kannst du über deren Index zugreifen, wobei zu beachten ist, daß das erste Element den Index 0 hat.Du brauchst natürlich für das obige Vorgehen noch eine Funktion Ersetzen, die man ohnehin immer wieder mal bei Strings benötigt. Falls du gerade keine elegantere Version zur Hand hast, geht es z. B. so:
AnsiString Ersetzen (AnsiString Text, AnsiString Such, AnsiString Ersetz) { AnsiString TText = Text; int position; int L = TText.Length(); if (!L) return TText; //gar nicht erst weiter machen position= TText.Pos(Such); while (position) { // löschen von "position" an, und zwar soviele Zeichen wie in Such stehen TText = TText.Delete(position, Such.Length()); // und den neuen String einführen TText = TText.Insert(Ersetz,position); position= TText.Pos(Such); } //while return TText; }
-
die korrekte Header (strutil.hpp) ist wohl erst ab dem BCB6 dabei. Da hab ich wohl Pech gehabt.
-
Ich arbeite auch noch mit dem Builder 5.
Was hast du gegen meinen Lösungsansatz ?
Ich finde das vergleichsweise elegant, einer Stringliste den modifizierten Text zu übergeben, die macht dann die Aufteilung in einzelne Elemente.
-
Deinen Lösungsansatz find ich gut, werd ich gleich mal ausprobieren. Ich will dann mal die Zeit messen ob es mit parsen schneller geht.
Meine Split-methode sieht so aus:
TStringList* TfrmMain::SplitString(AnsiString str, char delimiter) { TStringList* list = new TStringList(); int anzahlTrennz = 0; char* s_char = str.c_str(); for (int i=0; i<str.Length(); i++) { if (s_char[i] == delimiter) anzahlTrennz++; } for (int i=0; i<anzahlTrennz+1; i++) { if (i<anzahlTrennz) { list->Add(str.SubString(1, str.Pos(";")-1)); str = str.Delete(1, str.Pos(";")); } else list->Add(str); } return list; }
EDIT: und hier die Stringlistenversion:
TStringList* TfrmMain::SplitString2(AnsiString str, char delimiter) { TStringList *trennList(new (TStringList)); trennList->Text = StringReplace(str, delimiter, "\n", TReplaceFlags() << rfReplaceAll); return trennList; }
Ich habe mal Zeitmessungen mit dem QPT gemacht:
SplitString() ---> ca. 50 Mikrosek.
SplitString2() ---> ca. 80 Mikrosek.Der zeitliche Unterschied ist ja nicht so groß.
PS: Und ja, StringReplace gibt es unter dem BCB5 wie man sieht.
-
Hallo,
Die Funktion StringReplace sollte es eigentlich auch schon im BCB5 geben.
Ich finde es aber schon komisch, dass ihr den String bearbeitet wo ihr doch eigentlich nur lesen wollt.