![]() |
StringReplace und seine Tücken
Hallo,
benötigt werden 2 Memo-Felder und ein Button. Dazu folgender Code:
Delphi-Quellcode:
^^^Edit: Leerzeichen oben bei den ISO-Codes wegdenken - Der Editor hier übersetzt das als Zeichen!
procedure TForm1.Button1Click(Sender: TObject);
var i: integer; s: string; begin Memo1.Clear; Memo1.Lines.Add('Mustermann GmbH & Co. KG'); Memo1.Lines.Add(''); Memo1.Lines.Add('Täler, Wälder; all das ist Natur & schön.'); Memo2.Clear; for i := 0 to (Memo1.Lines.Count - 1) do begin s := StringReplace(Memo1.Lines[i], '&', '& # 3 8 ;', [rfReplaceAll]); s := StringReplace(s, ';', '& # 5 9 ;', [rfReplaceAll]); s := StringReplace(s, 'ä', '& # 2 2 8 ;', [rfReplaceAll]); Memo2.Lines.Add(s); end; end; Das Problem: Wenn StringReplace nun auf das &-Zeichen trifft, wird es korrekt übersetzt. Gleichzeitig wird aber auch geprüft, ob das Semikolon ( ; ) vorkommt - das wird ja aber schon mit dem Umsetzen vom &-Zeichen miterzeugt. Er schreib dann: Mustermann GmbH & # 3 8 & # 5 9 ; Co. KG (denkt euch die Leerzeichen weg, sonst interpretiert dies der Editor als Sonderzeichen). Ich wollte ![]() Hat jemand eine Idee, wie ich dieses rekursive verhalten von StringReplace umgehen kann? |
Re: StringReplace und seine Tücken
Zitat:
Ich versteh deinen Code nicht, oder viel mehr was der machen SOLL. Du ersetzt ein & durch ein & Was soll das denn werden?[/quote] Ausserdem, anstatt jede einzelne Zeile deines Memo1 zu durchlaufen, kannst du auch gleich so verfahren:
Delphi-Quellcode:
memo2.lines.text := StringReplace (memo1.lines.text,'&','&',[rfReplaceAll]) ;
|
Re: StringReplace und seine Tücken
Ich sehe da nix Rekursives.
Du machst erst ein StringReplace, wodurch du ein Semikolon einfügst. Danach machst du ein weiteres StringReplace, wo du das Semikolon durch etwas anderes ersetzt. Was erwartest du denn? Dass deine zweite Umwandlung deine erste vernachlässigt? Nimm doch eine andere Reihenfolge. |
Re: StringReplace und seine Tücken
Zitat:
Zitat:
Aber auch ein:
Delphi-Quellcode:
(^^^^Leerzeichen bei den ISO-Codes wegdenken!)
memo2.lines.text := StringReplace (memo1.lines.text,'&','& # 3 8 ;',[rfReplaceAll]) ;
memo2.lines.text := StringReplace (memo2.lines.text,';','& # 5 9 ;',[rfReplaceAll]) ; memo2.lines.text := StringReplace (memo2.lines.text,'ä','& # 2 2 8;',[rfReplaceAll]) ; ändert daran nichts - es wird "falsch" übersetzt. |
Re: StringReplace und seine Tücken
Zitat:
Ich bräuchte quasi eine Funktion, wo ich die zu suchenden und zu übersetzenden Tags z.B. als Array angeben kann, damit er mehrere auf einmal sucht und ersetzt. |
Re: StringReplace und seine Tücken
Genau, in der richtigen Reihenfolge ist es kein Problem. Wenn Du zuerst das & ersetzt, paßt doch alles.
Delphi-Quellcode:
Ich weiß, der Satz ist schwachsinnig, aber dadurch kommen ein paar Umlaute vor...
var
S: String; begin S := 'Hallöchen ältere Leute & Übrige Leser mit schönen Büchern'; S := StringReplace(S, '&', '"', [rfReplaceAll]); S := StringReplace(S, 'ä', 'ä', [rfReplaceAll]); S := StringReplace(S, 'ö', 'ö', [rfReplaceAll]); S := StringReplace(S, 'ü', 'ü', [rfReplaceAll]); S := StringReplace(S, 'Ä', 'Ä', [rfReplaceAll]); S := StringReplace(S, 'Ö', 'Ö', [rfReplaceAll]); S := StringReplace(S, 'Ü', 'Ü', [rfReplaceAll]); ShowMessage(S); end; Problematisch ist es, wenn Du den geänderten Text durch ShowMessage anzeigen läßt, hier scheinen die &-Zeichen verschwunden zu sein (in Wirklichkeit werden sie nur nicht angezeigt, weil sie zur Kodierung der unterstrichenen Buchstaben verwendet werden). |
Re: StringReplace und seine Tücken
Zitat:
Aber auch da habe ich schon rumgebastelt und Dinge getauscht - mit dem Ergebnis, daß es dann an anderen Stellen "falsch" ist. Ich will mir gar nicht vorstellen, was passiert, wenn ich noch das #-Zeichen übersetzen möchte... :? Zitat:
|
Re: StringReplace und seine Tücken
Zitat:
@ Catbytes Du könntest zuerst das ; ersetzen und dann in einem IF zuerst prüfen, ob auf das & ein # folgt bevor du das & ersetzt. vielleicht etwas aufwändig, aber so könnte es gehen... |
Re: StringReplace und seine Tücken
Ersetze zuerst das "#" und das ";". Danach machst du den Rest.
|
Re: StringReplace und seine Tücken
Zitat:
|
Re: StringReplace und seine Tücken
Zitat:
Delphi-Quellcode:
(^^^^Leerzeichen bei den ISO-Codes wegdenken!)
procedure TForm1.Button1Click(Sender: TObject);
var i: integer; s: string; begin Memo1.Clear; Memo1.Lines.Add('Mustermann GmbH & Co. KG'); Memo1.Lines.Add(''); Memo1.Lines.Add('Täler, Wälder; all das # ist Natur & schön.'); Memo2.Clear; for i := 0 to (Memo1.Lines.Count - 1) do begin s := StringReplace(Memo1.Lines[i], '#', '& # 3 5 ;', [rfReplaceAll]); s := StringReplace(s, ';', '& # 5 9 ;', [rfReplaceAll]); s := StringReplace(s, '&', '& # 3 8 ;', [rfReplaceAll]); s := StringReplace(s, 'ä', '& # 2 2 8 ;', [rfReplaceAll]); Memo2.Lines.Add(s); end; end; Ergibt: Mustermann GmbH & # 3 8 ; Co. KG T& # 2 2 8 ;ler, W& # 2 2 8 ;lder& # 3 8 ; # 5 9 ; all das & # 3 8 ; # 3 5 & # 3 8 ; # 5 9 ; ist Natur & # 3 8 ; schön. (^^^^Leerzeichen bei den ISO-Codes wegdenken!) :cry: Edit: diComm war schneller :P |
Re: StringReplace und seine Tücken
Muss das ; überhaupt ersetzt werden? Das ist doch im normalen Zeichenvorrat drin.
|
Re: StringReplace und seine Tücken
Zitat:
|
Re: StringReplace und seine Tücken
@Catbytes:
Ein bisschen mehr Fantasie. Erst das ";" und dann das"#". :zwinker: |
Re: StringReplace und seine Tücken
Zitat:
|
Re: StringReplace und seine Tücken
Zitat:
Delphi-Quellcode:
Ergibt:
s := StringReplace(Memo1.Lines[i], ';', ';', [rfReplaceAll]);
s := StringReplace(s, '#', '#', [rfReplaceAll]); s := StringReplace(s, '&', '&', [rfReplaceAll]); s := StringReplace(s, 'ä', 'ä', [rfReplaceAll]); Mustermann GmbH & # 3 8 ; Co. KG T& # 2 2 8 ;ler, W& # 2 2 8 ;lder& # 3 8 ; & # 3 8 ; # 3 5 ; 5 9; all das & # 3 8 ; # 3 5; ist Natur & # 3 8 ; schön. :cry: Zitat:
Trotzdem danke für die Tipps. Egal wie ich es drehe und wende: eine Sache wird immer "falsch" ersetzt. Noch andere Ideen? |
Re: StringReplace und seine Tücken
Zitat:
Zitat:
|
Re: StringReplace und seine Tücken
Aber etwas zu Deinem Problem ...
Was hindert dich daran eine zweite Stringlist zu verwenden, wo Du das konvertierte reinschreibst? Ich stell mir das so vor: Du gehst Dein Memo zeichen für Zeichen durch und schreibst das konvertierte in die neue Stringlist, dann ist es ziemlich egal, welche Reihenfolge du verwendest. |
Re: StringReplace und seine Tücken
Mist. Habe "&" nicht bedacht.
Ich denke der Weg von GuenterS ist die sinnvollste Möglichkeit, falls es nicht noch ein spezielle Konvertierungsfunktion dafür gibt. |
Re: StringReplace und seine Tücken
Zitat:
|
Re: StringReplace und seine Tücken
Zitat:
Delphi-Quellcode:
Ergibt:
function GetISO8859_1(s: string): string;
var i: Integer; sNew: string; begin sNew := ''; for i := 1 to Length(s) do begin case s[i] of ';': sNew := sNew + '& # 5 9 ;'; '#': sNew := sNew + '& # 3 5 ;'; '&': sNew := sNew + '& # 3 8 ;'; 'ä': sNew := sNew + '& # 2 2 8 ;'; // Hier folgen weitere ISO-Codes... else sNew := sNew + s[i]; end; end; Result := sNew; end; procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin Memo1.Clear; Memo1.Lines.Add('Mustermann GmbH & Co. KG'); Memo1.Lines.Add(''); Memo1.Lines.Add('Täler, Wälder; all das # ist Natur & schön.'); Memo2.Clear; for i := 0 to (Memo1.Lines.Count - 1) do begin Memo2.Lines.Add(GetISO8859_1(Memo1.Lines[i])); end; end; Mustermann GmbH & # 3 8 ; Co. KG T& # 2 2 8 ;ler, W& # 2 2 8 ;lder& # 5 9 ; all das & # 3 5 ; ist Natur & # 3 8 ; schön. :thumb: :-D Danke euch allen... Werde die komplette Function dann hier noch posten, wenn ich alles abgeschrieben habe. Entdeckt noch jemand einen (logischen) Fehler oben im Code? Kann man an irgend einer Stelle Code einsparen oder verbessern? |
Re: StringReplace und seine Tücken
Es gibt einen "Fehler" ... Du wirst im Memo2 nur 1 Zeichen bzw. den Code für das Konvertierte Zeichen in einer Zeile haben.
|
Re: StringReplace und seine Tücken
Zitat:
In Memo2 kam genau das gleiche raus, wie in Memo1 - nur eben übersetzt. Mit Umbrüchen und allem... Was genau meinst Du? |
Re: StringReplace und seine Tücken
Die Lines Property vom Memo ist ja eigentlich auch nur ein TStrings Typ. Wenn Du da für jedes Zeichen Add aufrufst hast Du es nachher nicht mehr so drinnen wie du es im Ursprünglichen Memo hast, auch wenn es ein Memo vielleicht anders darstellt.
versuch doch mal nach der Konvertiertung den Inhalt von Memo2 zeilenweise in eine Datei zu schreiben, dann dürftest Du schön sehen was ich meine. |
Re: StringReplace und seine Tücken
Zitat:
Habe es mal spaßhalber per SaveDialog und Memo2.Lines.SavetoFile gespeichert. Alles sauber... Wenn ich es jetzt immer noch nicht verstanden habe :gruebel: Hättest du zwei oder drei Zeilen Code für mich, was genau Du meinst? |
Re: StringReplace und seine Tücken
Ich zieh meinen Kommentar zurück, hab mich verschaut. Dachte gesehen zu haben, dass du es zeichenweise in die Konvertierungsroutine schickst... :duck:
|
Re: StringReplace und seine Tücken
Zitat:
Danke Dir trotzdem für die Hilfe! :-D |
Re: StringReplace und seine Tücken
Hallo Catbytes!
Bei solchen Problemen ist es eine gute Idee, das "kritische" Zeichen (hier '&') bei den Ersetzungen durch ein garantiert nicht im String vorkommendes Zeichen (z.B. #02) zu ersetzen. Dann kommt kein '&' in den Text, das nicht umgesetzt werden muß. Als letzte Aktion ersetzt Du dann das Hilfszeichen durch das '&'. Ansonsten geht nur der Weg, den Text zeichenweise durchzugehen. Dazu sollte man den String zweimal durchgehen: erst ermittelt und summiert man für jedes Zeichen die Länge im Ergebnis, setzt dann den Ausgabestring auf diese Summe und kopiert zeichenweise das Zeichen bzw. den Ersatzstring. Bitte nicht den Ergebnisstring durch Verketten erzeugen - die ständige Umkopiererei frißt gewaltig Speicher. Gruß Dietmar Brüggendiek |
Re: StringReplace und seine Tücken
Zitat:
Delphi-Quellcode:
oder eine (oder mehrere) ähnliche Zeile(n) benutzen, also die falschen Kombinationen wieder ersetzen. (Leerzeichen wie gehabt)
memo2.lines.text := StringReplace(memo1.lines.text,'& # 3 8 & # 5 9 ;','& # 3 8 ;',[rfReplaceAll]);
|
Re: StringReplace und seine Tücken
Moin Phistev,
Zitat:
Besser ist es sie einmal in eine Stringvariable zu übernehmen, dann mit dieser zu arbeiten, und anschliessend wieder in Memo1.Lines.Text zurückzuschreiben (so wie Catbytes dass auch gemacht hat). Grund: Beim jedem Lesen der Eigenschaft, wird Text aus den einzelnen Lines zusammengesetzt, beim Schreiben werden die Lines jeweils neu erzeugt. Das drückt, je nach Textlänge, reichlich auf die Performance. @Dietmar: Als Kompromiss für die Errechnung der Buffergrösse, die ja auch Zeit in Anspruch nimmt, könnte man auch einen Schätzwert für die erforderliche Grösse annehmen (Basis wieviele Zeichen müssen durchschnittlich ersetzt werden), und beim Überschreiten dieses Wertes den Buffer um einen festgelegten Wert erhöhen (in der Hoffnung, dass das nicht notwendig sein sollte) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz