Auslesen zwischen zwei Zeichen???
-
Moin,
bin neu hier zu euch dazugestoßen,
mein erster Post = erste FrageAlso gehen wir mal davon aus das ich folgenden inhalt in einer memo habe:
A;-22;69;90;7;
wie kann ich denn den inhalt zwischen jewils zwei Semikola auslesen und an eine bestimmte Position in der Memo quasi schieben?
Help i need somebody...
-
Ok, dann schau Dir mal die Eigenschaft TMemo::Lines an. Dies ist ein TStrings-Objekt. Sprich jede einzelne Zeile des Memos wird durch ein AnsiString-Objekt repräsentiert.
Und AnsiString verfügt über die Methoden AnsiPos() und SubString().Genauere Hilfe ist nur bei genauerer Beschreibung des Problems möglich, aber vielleicht helfen Dir diese Stichpunkte ja schon weiter.
-
Leider wiess ich damit nicht grad viel anzufangen (wg Anfänger).
srywärst du so net mir das an einen kleenen beispiel code zu zeigen?
BÖÖÖÖTTTEEE
-
Bei solch einem Beispiel würde ich die Eigenschaft 'delimitedText' von TStringList vorziehen, da spart man sich die viele Mühe mit AnsiPos und Substring.
Wenn nur ein Delimiter (hier das Semikolon) im Spiel ist, lohnt sich der Aufwand nicht, den String selber zu zerlegen.
-
Ich habe jetzt hin und her probiert aber es wird nix...
A;-22;69;90;7; B;123,25;-12,325;95,2;58,87
soll hinterher so aussehen
A -22 +69 B 123,25 -12,325
das problem:
die letezen ziffern (90 und 7 sowie 95,2 und 58,87) müssen gelöscht werden.
und die abstände müssen eingehalten werden.
siehe beispiel Bvorher:
B;123,25;-12,325;95,2;58,87
Hinterher:
B 123,25 -12,325
hier habe ich ja wieder zahlen die mehr platz einehmen.
und das variert immer.A -22 +69 B 123,25 -12,325
also die zahlen müssen immer an der selben stelle anfangen!!!
wäre für nen snippet wäre ich echt mega dankbar
Grüsse
euer EISI
-
HILFEEE!!!!
-
Eisi schrieb:
Ich habe jetzt hin und her probiert aber es wird nix...
Was genau hast du probiert? Wo ist dein Code?
-
könnt ihr mir nicht bitte einfach nen beispiel code posten?
ich kriege es nicht hin...
gegoogelt hab ich scho...und über die suchen funktion finde ich nichts...
-
Zeig doch einfach mal, was Du bisher versucht hast.
-
bin auf der Arbeit deswegen hab ich den code net hier.
habe mit StringPos versucht die ";" position rauszufinden
und diese position mit "move" auf eine andere zu schieben.
abeer da mehrer ; in einer zeile sind klappt das net...
-
Du hast doch hier mehrere Möglichkeiten.
1. Nutze TStringList und DelimitedText mit Semikolon als Delimiter /(am einfachsten)
2. Bei Pos (bzw. AnsiPos) könntest du nach Finden des ersten Semikolons und holen deines ersten Strings mit SubString den Teil im Hauptstring bis zum Semikolon mit Delete(index, count) löschen.
3. Nimm statt AnsiString std::string. Dort kannst du deine Semikolons mit find(";", pos) ab der angegebenen Stelle suchen, dann mit substr den gewünschten string ausschneiden und dann fortfahren.
-
Ja aber mit substring muss ich ja die länge des strings definieren,
und das kann ich ja net weil die Zahlen immer untersdchiedlich lang sind.
-
Du mußt doch nur nach dem nächsten Semikolon suchen. Also:
- Semikolon suchen
- Semikolon an Position löschen (Delete)
- nächstes Semikolon suchen, Position gibt Länge des Strings,
usw.
-
Ich bin einfach einmal so frech, und poste meine strExplode-Funktion
void strExplode(TStringList *returnarray, String Zeile, char Trennzeichen, char quote, char escape) { String column = ""; if (Zeile.SubString(Zeile.Length(), 1) != Trennzeichen) Zeile = Zeile + Trennzeichen; bool isQuoted = false; returnarray->Clear(); for (int i = 1; i <= Zeile.Length(); ++i) { if (Zeile.SubString(i,1) == quote) { if (Zeile.SubString(i-1, 1) != escape) isQuoted = !isQuoted; else column = column + quote; } else if ((Zeile.SubString(i,1) == Trennzeichen) && (!isQuoted)) { returnarray->Add(column); column = ""; } else if (!((Zeile.SubString(i,1) == escape) && (Zeile.SubString(i+1,1) == quote))) column = column + Zeile.SubString(i,1); } }
-
kannst du mir deine funktion a bissl erläutern???
bin noch anfänger.und wie kriege ich das in mein memo umgesetzt?
-
nun gut:
Die Funktion zerlegt eine Zeichenkette, die z.B. im CSV-Format vorliegt. Eine solche Zeile mit Werten könnte z.B. so aussehen:
"Ich";"Bin";"eine";"Beispielzeile und";"kann im Text auch Anführungsstriche \" und Semikolons ; enthalten"Die Funktion erwartet 5 Parameter:
TStringList *returnarray: Das muss eine mit "new" bereits erstellte TStringList sein, in welcher die einzelnen Werte dann Zeile für Zeile gespeichert werden. Wenn die zu trennende Zeile aus 5 Spalten besteht, enthält die StringList hinterher 5 Zeilen.String Zeile: Das ist der Original-String, der zerlegt werden soll
char Trennzeichen: Das Trennzeichen, mit welchem die einzelnen Spalten getrennt sind
char quote: Das ist im Normalfall das Anführungszeichen " - und gibt an, wie die Werte eingeschlossen sind. Das ist notwendig, damit auch Trennzeichen in den Werten enthalten sein können, ohne dass die Funktion daraus eine Spalte macht.
char escape: Das ist das Escape-Zeichen für das Anführungszeichen. Möchte man also in einem Text ein Anführungszeichen verwenden, stellt man dem Anführungszeichen das Escape-Zeichen voran. Also z.B: \" - wobei das Escape-Zeichen dann der Backslash \ und das Quote-Zeichen das Anführungszeichen " ist.
Die Funktion selbst läuft dann Zeichen für Zeichen den Originalstring durch, überprüft ob es sich um ein Trennzeichen handelt - wenn ja, prüft es, ob es in Anführungszeichen eingeschlossen ist, und ob ein Anführungszeichen "escaped" ist. Ich bin mir nicht sicher, ob man die Funktion mittels "SubString" und "Pos" evtl. performanter gestalten könnte, mag sein - auf der anderen Seite kann ich mir gut vorstellen, dass auch die Funktion AnsiString::Pos nichts anderes macht, als den String Zeichen für Zeichen zu durchsuchen.
Nachfolgend noch einen Beispielaufruf der Funktion (ungetestet)
String csvZeile = "'Hallo;';'in Hochkomma (\')';eingeschlossene;\'Welt\'"; TStringList *werte = new TStringList(); strExplode(werte, csvZeile, ';', '\'', '\\'); //Jetzt alle Werte aus der StringList, Wert für Wert anzeigen: for (int w = 0; w < werte->Count; ++w) { ShowMessage(werte->Strings[w]); } delete werte;
-
Hei, Eisi
setze diese Funktion ein (überall das | gegen ; ersetzen, ich benutze bei mir immer das Pipe | als Trenner):
//---------------------------------------------------------------------------- //----- DATENPIPE ----- //---------------------------------------------------------------------------- AnsiString DatenPipe(int p1, int p2, AnsiString pt1, AnsiString pt2) {try { // Fehlerroutine Start Integer i2,i3; AnsiString z1,z2; // Vars definieren if(pt1.Length()==0) { pt1="||"; } // Stringvorgabe korrigieren z1=pt1; // und übergeben switch(p1) { // was machen? case 1: // AUSLESEN STRING case 3: // AUSLESEN INTEGER for(int i1=1;i1<=p2;i1++) { // x. Pipe suchen i2=z1.AnsiPos("|"); // Pipe suchen if(i2==0) { z1=z1+"|"; i2=z1.AnsiPos("|"); } // keines gefunden, neues Pipe anhängen z1=z1.SubString(i2+1,9999); // String ab Pipe+1 abschneiden } // ende for(int i2) i2=z1.AnsiPos("|"); // noch nächstes Pipe suchen z1=z1.SubString( 1,i2-1); // und bis nächstes Pipe den Inhalt ausschneiden return z1; // und Inhalt zurückgeben case 2: // SCHREIBEN z2=""; // String vorbereitend löschen for(int i1=1;i1<=p2;i1++) { // x. Pipe suchen i2=z1.AnsiPos("|"); if(i2==0) { z1="|"; i2=1; } // Pipe suchen und ggfs. anhängen z2=z2+z1.SubString(1, i2); // und Rest merken z1=z1.SubString(i2+1,9999); // String ab Pipe+1 abschneiden } // ende for(int i2) i2=z1.AnsiPos("|"); // noch nächstes Pipe suchen z1=z2+pt2+z1.SubString(i2, pt1.Length()); // und pt2 einsetzen und ab nächstem Pipe anhängen if(z1.SubString(z1.Length(),1)!="|") { z1=z1+"|"; } // hinten fehlt ein Pipe, einsetzen return z1; // und Inhalt zurückgeben } // ende switch(p1 return ""; // Standardrückgabe } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "Funktion DatenPipe()", MB_OK); return ""; } // Fehler anzeigen }
Und so aufrufen zum Auslesen:
AnsiString z1,z2; z1=";0.20;0,090;1292;....;usw.;"; z2=DatenPipe(1, x, z1, ""); // Auslesen x=Position 1....99999 ShowMessage("Inhalt aus Position x: "+z2);
Und so aufrufen zum Beschreiben:
AnsiString z1,z2,z3; z1=";0.20;0,090;1292;....;usw.;"; z3="neu einsetzen" z2=DatenPipe(1, x, z1, z3); // Inhalt z3 einsetzen an x.Position 1....99999 ShowMessage("Neuer String mit neuem Inhalt an Position x: "+z2);
Gruss Stefan
-
Hallo Stefan.
Also macht dein kleines Proggi genau das was ich wollte?!
statt show message kann ich den ganzen kram dann in ein memo bringen?
muss der code in tform1 mit rein?
gruß Eisi
-
wie wende ich das denn dann auf ein memo an?
-
bist du dir sicher das du das in einem memo haben möchtest? ein stringgrid würde doch viel besser passen...
und um raus zu finden was sein programm genau macht... debugs doch mal durch