Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Zeichen in String ersetzen (https://www.delphipraxis.net/191202-zeichen-string-ersetzen.html)

JanWe 19. Dez 2016 23:02

Zeichen in String ersetzen
 
Betrifft:
DELPHI 5

Hi,

VORGESCHICHTE:
eine Freundin von mir hat für eine Studie Versuche mit diversen Programmen und Verfahren durchgeführt und diese Ergebnisse mit Programmen wie u.a. SPSS, Excel, usw. bearbeitet.
Doch leider ist es zum Gau gekommen, da sie mehrere OriginalDateien überschrieben hat. (dauert jetzt zu lange das detailliert zu erklären).
Die Daten sind zwar glücklicherweise noch einmal vorhanden, allerdings quer in 1 Datei verwurstet.

PROBLEM:
Jetzt hab ich ihr versprochen, ich würde ihr dabei helfen.
Und hab versucht ein Programm zu entwickeln, das nach Zeichen sucht und diese Daten extrahieren oder zumindest erstmal trennen kann.

Dabei soll bei Auftreten von 3 Zeichenkombinationen wie folgend verfahren werden: (für mich sind es nachher noch mehr, aber wenigstens die schon mal ..)
  1. X01 soll durch den String ' Typ A: ' (steht für Fragetyp A) ersetzt werden
  2. 01 steht für ' Typ B: ' (für Fragetyp B)
  3. die Datenseparator (Komma ',') sollen, falls sie mehrfach vorkommen durch ein einzelnes Vorkommen ersetzt werden

Delphi-Quellcode:
procedure TForm1.Button8Click(Sender: TObject);
var Rest, s, TEX: string;
  Menge, Laenge, i: Integer;
begin
//   Beispielkette
  S := '2,9,0171,,25,01640X0174,01747,23,,,,47X014747'; //

  S := '0,,25,01640X0174,01747,23,,,,47X014747'; // vorne gekürzte Kette bringt wieder andere Ergebnisse
  laenge := length(s);
  i := 0;
  Menge := 0;
  while i < laenge do
  begin
    inc(i);
      if (s[i] = 'X') and (s[i + 1] = '0') then // -> x0
    begin
      if (s[i + 2] = '1') then // -> wenn X01
        if Menge > 0 then
        begin
          TEX := TEX + ',' + ' Typ: A ';
          Menge := 0;
        end
        else
          TEX := TEX + ' Typ: A ';
      inc(i);
    end
    else ////////////////////////////////////
      if (s[i] = '0') and (s[i + 1] = '1') then // -> normaler 01
      begin
        if Menge > 0 then
        begin
          TEX := TEX + ' Typ: B '; // Antworttyp
          Menge := 0;
        end
        else TEX := TEX + ',' + ' Typ: B '; // Antworttyp B
        inc(i);
      end
      else ////////////////////////////////////
        if (s[i] = ',') then // DOPPELTE Trenner finden
        begin
          inc(Menge);
        end
        else ////////////////////////////////////

          if Menge > 0 then
          begin
            Caption := s[i];
            if Menge = 1 then
              TEX := TEX + ',' + s[i]
            else
              TEX := TEX + s[i];
           Menge := 0;
          end
          else
        // alles andere
       
            TEX := TEX + s[i]; // alle anderen Zeichen

  end; // END WHILE
  Memo2.text := TEX;
  Memo1.text := S;

end; // Ende Buttonfunktion
Ich hab jetzt seit Freitag immer wieder rumprobiert und mit mehreren Zeichenketten [s.o.] versucht.
Jedes Mal kamen andere, neue Verluste von Zeichen heraus.

Aus der folgenden Zeichenkette z.B.
0,,25,01640X0174,01747,23,,,,47X014747

025 Typ: B 640 Typ: A174 Typ: B 747,2347 Typ: A 14747
kommt ^^ => d.h.
(1. Doppelkomma => verschwindet ganz,
Komma nach der 25 ist auch weg
aus X01 wird aber die 1 dennoch übernommen
Komma verschwindet, usw.) - aber das ist ja nicht richtig!

Ich hab zwar jetzt an so vielen Stellen herumgeschraubt und verbessert,
aber es will nicht komplett gelingen.

Sieht vielleicht einer von Euch, woran es liegt?
oder gibt es am Ende eine komplett einfachere Lösung? (ich habe keine Informatikerausbildung und Algorithmenentwicklung nicht nativ gelernt)

Vielen Dank.

himitsu 19. Dez 2016 23:23

AW: Zeichen in String ersetzen
 
Warum machst du es dir so schwer und versuchst alles gleichzeitig und auch "Mehrfachzeichen" mit Einzelzeichenoperationen zu verarbeiten?

Wenn/da es nicht auf's Tempo ankommt.

Delphi-Quellcode:
while ContainStr(S, ',,') do // nach zwei Durchläufen sind auch ',,,' nur noch ',' usw.
  S := ReplaceStr(S, ',,', ',');
Und dannach
Delphi-Quellcode:
S := ReplaceStr(S, 'X01', '' Typ A: ');
S := ReplaceStr(S, '01', '' Typ B: ');
Man kann natürlich auch mit Pos/PosEx Zeichenketten suchen und über Delete+Insert ersetzen.
Oder per RegEx nach "mehreren" Kommas suchen und sie durch ein ',' ersetzen.

Mit 2 TStringList kann man auch Einzelzeilen und darin einzelne Teilstrings verarbeiten.
Erste StringList für die Zeilen und dann jeweils eine Zeile in TStringList.CommaText oder TStringList.DelimitedText kopieren.
In der 2. StringList alle Werte ohne inhalt löschen und in den einzelwerten das ReplaceStr anwenden.
Nach auslesen und zurückschreiben des CommaText sind dann auch mehrfache Kommas aufgelöst (",," ist ein Leerstring zwischen den Kommas :zwinker:)
und auch Kommas am Anfang und Ende sind weg (falls man beim Delete nicht den ersten und letzten Leerstring beibehält).

JanWe 20. Dez 2016 00:02

AW: Zeichen in String ersetzen
 
Hi,

danke Dir für Deine Antwort:
Allerdings muß ich dazu sagen, dass ich nur Delph 5 habe (und derzeit keinen Platz, um Lazarus oder eine Trial zu installieren, da ich gerade wichtige Planungsvideos auf meinem Laptop habe.

Mhh, ja, sicher ist da viel auf einemal.
Angefangen hatte ich auch erst nur mit den x01 und 01 (Typ A; Typ B) Zeichenketten und die bearbeitet. Das ging auch gut.

Dann dachte ich mir .. Ok, die restlichen kannste ja noch mit Kommt ein Komma vor oder wenn, sogar mehrere ...


und eigentlich würde ich das gerne mit Pointern machen (darum auch der Inc()-operator und einzelne Vegleich

hier nochmal der VErsuch einer verkürzten Version der oben ... aber ich seh gerade, der Übersicht hilft das gar nicht.
und die Ergebnisse sind auch wieder total andere:

0,,25,01640X0174,01747,23,,,,47X014747
wird zu
025, Typ B: ,640, Typ A: 174, Typ B: ,747,2347, Typ A: 14747
Delphi-Quellcode:
procedure TForm1.Button9Click(Sender: TObject);
var Rest, s, TEX: string;
  Menge, Laenge, i: Integer;
begin
//      8 8  88           888  X01
  S := '2,9,0171,,25,01640X0174,01747,23,,,,47X014747'; //

  S := '0,,25,01640X0174,01747,23,,,,47X014747'; //
  laenge := length(s);
  i := 0;
  Menge := 0;
  while i < laenge do
  begin
    inc(i);
    if s[i] = '5' then
      Caption := s[i];
    if (s[i] = 'X') and (s[i + 1] = '0') then // -> x01
    begin
      if (s[i + 2] = '1') then // wenn X01
            TEX := TEX + ',' + ' Typ A: ';
      inc(i);
    end
    else ////////////////////////////////////
//      Caption := s[i];
      if (s[i] = '0') and (s[i + 1] = '1') then // normaler 01
      begin
        TEX := TEX + ',' + ' Typ B: ';
        inc(i);
      end
      else ////////////////////////////////////
        if (s[i] = ',') then // and (s[i + 1] = ',') then // DOPPELTE Trenner finden
        begin
          inc(Menge);
        end
        else ////////////////////////////////////

          if Menge > 0 then
          begin
            Caption := s[i];
            if Menge = 1 then
              TEX := TEX + ',' + s[i]
            else
              TEX := TEX + s[i];
            Menge := 0; //     
          end
          else
            TEX := TEX + s[i]; // LAST CHANGE


  end; // END WHILE
  Memo2.text := TEX;
  Memo1.text := S;
end; //
Mit Regex usw. kenn ich mich gar nicht aus. ...

nahpets 20. Dez 2016 01:17

AW: Zeichen in String ersetzen
 
Überprüfe bitte mal, ob die inc(i) immer korrekt sind. Inc(i) entspricht halt i := i + 1. Aber bei x01 verarbeitest Du doch drei Zeichen, demnach müsstest Du hier auch i := i + 3 machen statt inc(i).
Bei 01 wäre es dann i := i + 2;

Bin mir nicht sicher, ob ich die Logik verstanden habe, es ist doch schon etwas zu früh - sorry spät ;-)
Quelltext hab' ich mal angepasst und ein bisserl kommentiert, aber nicht getestet.
Delphi-Quellcode:
procedure TForm1.Button9Click(Sender: TObject);
var Rest, s, TEX: string;
  Menge, Laenge, i: Integer;
begin
  // 8 8 88 888 X01
  S := '2,9,0171,,25,01640X0174,01747,23,,,,47X014747'; //

  S := '0,,25,01640X0174,01747,23,,,,47X014747'; //
  laenge := length(s);
  i := 1;
  Menge := 0;
  while i < laenge do begin
    if s[i] = '5' then Caption := s[i];
    // -> x01
    if (s[i] = 'X') and (s[i + 1] = '0') then begin
      // wenn X01
      if (s[i + 2] = '1') then begin
        TEX := TEX + ',' + ' Typ A: ';
        inc(i,2);
      end;
    end else ////////////////////////////////////
    // Caption := s[i];
    // normaler 01 
    if (s[i] = '0') and (s[i + 1] = '1') then begin
      TEX := TEX + ',' + ' Typ B: ';
      inc(i); // Sonst finden wir im nächsten Durchgang die 1 und geben sie aus.
    end else ////////////////////////////////////
    // DOPPELTE Trenner finden
    if (s[i] = ',') then begin // and (s[i + 1] = ',') then
      inc(Menge); // Zählt die Anzahl der , ???
    end else ////////////////////////////////////
    if Menge > 0 then begin
      // Hier kommen wir nur hin, wenn Menge > 0
      // und keine der anderen Bedingungen erfüllt ist.
      // Kann hier jemals ein Komma ausgegeben werden, dass vor X01 bzw. 01 steht?
      Caption := s[i];
(*
      if Menge = 1 then TEX := TEX + ',' + s[i]
      // Ist Menge jedoch > 1, wird kein Komma ausgegeben.
      // Geht uns da nicht bei mehreren Kommas was verloren?
      // Hier dürfte die Ursache für das fehlende Komma zwischen 0 und 25 liegen.
      else TEX := TEX + s[i];
*)
      // Würde hier nicht das reichen?
      // Egal wieviele wir gefunden haben, wir geben nur eins aus.
      TEX := TEX + ',' + s[i];
      Menge := 0; //
    end
    else TEX := TEX + s[i]; // LAST CHANGE
    inc(i);
  end; // END WHILE
  Memo2.text := TEX;
  Memo1.text := S;
end; //
Kennt Delphi 5 schon die Funktion AnsiReplaceText aus der Unit StrUtils?

Wenn ja, dann ließe sich das Problem eventuell so lösen:
Delphi-Quellcode:
s := '0,,25,01640X0174,01747,23,,,,47X014747';
s := AnsiReplaceText(s,'X01',' Typ A: ');
s := AnsiReplaceText(s,'01',' Typ B: ');
while Pos(',,',s) > 0 do begin
  s := AnsiReplaceText(s,',,',',');
end;
Ansonsten eventuell:
Delphi-Quellcode:
s := '0,,25,01640X0174,01747,23,,,,47X014747';
s := StringReplace(s,'X01',' Typ A: ',[rfReplaceAll, rfIgnoreCase]);
s := StringReplace(s,'01',' Typ B: ',[rfReplaceAll, rfIgnoreCase]);
while Pos(',,',s) > 0 do begin
  s := StringReplace(s,',,',',',[rfReplaceAll]);
end;

bcvs 20. Dez 2016 07:38

AW: Zeichen in String ersetzen
 
Ich würde da auch auf jeden Fall über eine Zeichenersetzungs-procedure gehen und da alle möglichen Fälle abarbeiten. Ist doch viel übersichtlicher.

Falls es in D5 noch kein ReplaceStr, AnsiReplaceText, StringReplace oder dergleichen gab, schreib dir einfach eine eigene. z.B.

Delphi-Quellcode:
function ReplaceString(StrOri, SuchStr, Repl:String):String;
var posi:integer;
begin
  posi:=pos(SuchStr, StrOri);
  while posi > 0 do begin
    StrOri:=copy(StrOri,1,posi-1)+ repl +
            copy(StrOri, posi+length(SuchStr), length(StrOri)-posi-length(SuchStr)+1);
    posi:=pos(SuchStr, StrOri);
  end;
  result:=StrOri;
end;
Und dann wie bereits vorgeschlagen:

Delphi-Quellcode:
s := '0,,25,01640X0174,01747,23,,,,47X014747';
s := ReplaceString(s,'X01',' Typ A: ');
s := ReplaceString(s,'01',' Typ B: ');
while Pos(',,',s) > 0 do begin
  s := ReplaceString(s, ',,', ',');
end;

DeddyH 20. Dez 2016 07:46

AW: Zeichen in String ersetzen
 
Nach meiner Kenntnis gibt es in Delphi 5 sehr wohl die StringReplace-Funktion.

ConnorMcLeod 20. Dez 2016 08:45

AW: Zeichen in String ersetzen
 
Du läufst den kompletten String Zeichen für Zeichen durch und merkst Dir die Chars, an denen Du vorbeikommst.
Deine längste "Kennung" ist drei Zeichen lang (X01). Also brauchst Du nur drei Char-Variablen, die Du in dieser Schleife füllst/schiebst und prüfst, ob eine der Kennungen vorkommt. Die korrekten Zeichen und die korrigierten/ersetzten Zeichen schreibst Du in einen neuen (Ergebnis-)String.
Oder Du schaust Dir mal an, wie ein Parser arbeitet ;-)

relocate 20. Dez 2016 09:15

AW: Zeichen in String ersetzen
 
Zitat:

Zitat von DeddyH (Beitrag 1356653)
Nach meiner Kenntnis gibt es in Delphi 5 sehr wohl die StringReplace-Funktion.

Die gibt es aber nicht ContainStr und ReplaceStr.

Leider stoße ich auch immer wieder auf so etwas. Gibt es eine Übersicht, ab wann welche Funktion in Delphi verfügbar ist. Auf den Emba-Seiten steht die Version so weit ich weiß nicht.

Luckie 20. Dez 2016 10:20

AW: Zeichen in String ersetzen
 
Was lernen wir daraus? Backup und nie mit den original Daten arbeiten. :?

p80286 20. Dez 2016 11:01

AW: Zeichen in String ersetzen
 
Zitat:

Zitat von bcvs (Beitrag 1356651)
Falls es in D5 noch kein ReplaceStr, AnsiReplaceText, StringReplace oder dergleichen gab, schreib dir einfach eine eigene.


Oder such nach FastCode, da solltest Du auch das eine oder andere finden.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:12 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz