Auslesen zwischen zwei Zeichen???



  • Moin,

    bin neu hier zu euch dazugestoßen,
    mein erster Post = erste Frage 😃

    Also 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).
    sry

    wä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 B

    vorher:

    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);
      }
    }
    


  • @rowisoft

    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 😃


Anmelden zum Antworten