Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Zeichen in Memo ersetzten und Formatierung beibehalten?! (https://www.delphipraxis.net/197535-zeichen-memo-ersetzten-und-formatierung-beibehalten.html)

Rawsche 14. Aug 2018 16:19

Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Hallo zusammen,

ich habe leider ein Problem. Ich möchte die Zeichen in einer Memo ändern doch es tritt ein Fehler auf, aus dem ich leider nicht schlau werde.

Delphi-Quellcode:
     
for i:=1 to Length(Memo1.lines.text) do
      begin
        x:=aendern(memo1.lines.Strings[i]);
        memo2.lines.Strings[i]:=x;
      end;
Die Prozedur "aendern" tauscht gewisse Zeichen aus Memo1 gegen andere aus. Diese veränderten Zeichen sollen, dann in Memo2 ausgegeben werden.

Die Fehlermeldung sieht wie folgt aus:


Projekt kompilieren, Ziel: project1.exe: Exit code 1, Fehler: 2
unit1.pas(60,44) Error: Can't take the address of constant expressions
unit1.pas(61,28) Fatal: Syntax error, "identifier" expected but "STRING" found



Ich versteh leider den Fehler nicht so richtig. Darf ich so nicht auf eine Memo zugreifen? Wie soll ich dann ein Zeichen ansprechen?


Und eine 2. Frage drängt sich mir noch auf. Wie kann ich Absätze aus einer Memo übernehmen? Ich möchte gern, dass Memo2 genau so aussieht wie Memo1 nur das z.B. Änderungen wie Sonderzeichen oder Großbuchstaben geändert werden. Deren sonstige Formatierung (Absätze) sollte aber beibehalten werden.

Ich würde mich sehr über eure Hilfe freuen.

Lg
Rawsche

KodeZwerg 14. Aug 2018 16:30

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Arbeitet schnarchlangsam aber erfüllt Sinn und Zweck.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
//  Memo2.Text := Memo1.Text;
//  Memo2.Text := StringReplace(Memo2.Text,'ErsetzeDas','MitDemHier',[rfReplaceAll]);
  Memo2.Text := StringReplace(Memo1.Text,'ErsetzeDas','MitDemHier',[rfReplaceAll]);
end;

himitsu 14. Aug 2018 16:45

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Zitat:

Delphi-Quellcode:
Length(Memo1.lines.text)

Wirklich die Anzahl der Zeichen oder doch lieber nur die Anzahl der Zeilen?
Delphi-Quellcode:
Memo1.Lines.Count
:stupid:

Und die Fehlermeldung passt zu keiner der gezeigten Codezeilen.
Was ist denn in Zeile 60?

Und hat Memo2 überhaupt genug Zeilen? (vielleicht besser vorher
Delphi-Quellcode:
Lines.Clear
und dann
Delphi-Quellcode:
Lines.Add
)

Außerdem ist ein Memo sehr langsam, vorallem wenn man kein
Delphi-Quellcode:
Lines.BeginUpdate
und
Delphi-Quellcode:
Lines.EndUpdate
drumrum macht.
Oder besser in eine StringList umkopieren, da drin ändern und "einmal" deren Text dann an Memo2 zuweisen.

KodeZwerg 14. Aug 2018 16:59

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Ich habe mal was gebastelt was auch mehrere Änderungen zulässt.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  iLines, iString: Integer;
  tmp, finish: string;
begin
  finish := '';
  for iLines := 0 to Memo1.Lines.Count -1 do // -1 eingefügt @ himitsu
  begin
    tmp := Memo1.Lines.Strings[iLines];
    for iString := 1 to Length(tmp) do
    begin
      case tmp[iString] of
        Char('e'): tmp[iString] := 'E'; // Das dient mir als Beispiel, mach aus kleinem "e" ein Großes "E"
                                        // füge beliebig viele Vergleiche/Ersetze hier ein
        Char('E'): tmp[iString] := 'e'; // so wie hier, mach aus Großem "E" ein kleines "e"
      end;
    end;
    finish := finish + tmp + sLineBreak; // #13#10; ersetzt @ himitsu
  end;
  Memo2.Text := finish;
end;

Delphi.Narium 14. Aug 2018 17:05

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Der Zugrif auf Memo1.Lines.Text ist sehr langsam, vor allem, wenn im Memo viel Text drinne steht.

Etwas schneller wird es mit
Delphi-Quellcode:
Memo2.Lines.Clear;
for i := 0 to Memo1.Lines.Count - 1 do
begin
  Memo2.Lines.Add(StringReplace(Memo1.Lines[i],'ErsetzeDas','MitDemHier',[rfReplaceAll]));
end;

Luckie 14. Aug 2018 17:59

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Wie sieht den der Code von aendern aus? Da wird ja wahrscheinlich der Fehler liegen.

himitsu 14. Aug 2018 18:06

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Außerdem 1 bis Count oder wohl eher 0 bis Count-1, :zwinker:
aber 0 bis Count ist definitiv falsch.

Wobei ihr froh sein könnt, dass Memo zufällig keine Exception wirft, wenn man auf nichtexistierende Zeilen zugreift. (gibt da nur einen Leerstring raus)

#13#10 = sLineBreak


Und wie Lucke ebenfalls nochmal erwähnte:
Wie sieht der restliche Code aus?
Denn die genannten Fehlermeldungen kommen nicht aus dem gezeigten Codestück.




@Delphi.Narium:
Falsch, Memo1.Lines.Text ist schneller, denn Delphi (und bestimmt auch Lazarus) leiten das direkt an das Memo und holen den kompletten Text mit Einmal ab oder weisen ihn direkt zu,
genau so wie bei Memo.Text

Der Zugriff auf Einzelzeilen (Lines[]) ist langsam, vor allem beim Ändern und wenn viel Text im Memo steht.

KodeZwerg 14. Aug 2018 18:47

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Hab Fehler gefixt, Danke himitsu.:thumb:

Rawsche 14. Aug 2018 21:03

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich werde mal die Karten komplett offen auf den Tisch legen. Bitte nicht lachen, falls ihr eine bessere Methode kennt, aber ich versuche in ein Programm eine Art Verschlüsselung einzubauen und habe daher zu Testzwecken das folgende Programm geschrieben.

Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids,
  StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    ListBox2: TListBox;
    Memo1: TMemo;
    Memo2: TMemo;
    Memo3: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    procedure Coding(var x: string);
    procedure Decoding(var x: string);

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Coding(var x:string);
var i:integer;
begin
  for i:=0 to listbox1.items.count-1 do
  if x=listbox1.items[i] then x:=listbox2.items[i];
end;

procedure TForm1.Decoding(var x:string);
var i:integer;
begin
  for i:=0 to listbox2.items.count-1 do
  if x=listbox2.items[i] then x:=listbox1.items[i]
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
  x:string ;
begin
      for i:=1 to Length(Memo1.lines.text) do
      begin
        x:=coding(memo1.lines.Strings[i]);
        memo2.lines.Strings[i]:=x;
      end;
end;

end.
Anbei noch ein Bild meines Formulares.

Ich hoffe euch wird klar, was ich mir gedacht hatte. Ich würde, auch wenn es vielleicht einfacher geht, ungern anders vorgehen, weil ich gerade erst ins Verschlüsseln eingestiegen bin und gerne mit Tausch-Chiffrierung beginnen möchte.

Ich freue mich auf eure Ideen. Bitte berichtigt NICHT einfach den Code, sondern gebt mir vielleicht lieber Tipps, wie ich ihn selbst verbessern kann. Sonst lerne ich daraus leider nichts...


LG und Danke für die schon jetzt zahlreichen Antworten
Rawsche

Luckie 14. Aug 2018 21:05

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Und wieder fehlt der entscheidende Code: coding. :roll:

Uwe Raabe 14. Aug 2018 21:14

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Zitat:

Zitat von Luckie (Beitrag 1410659)
Und wieder fehlt der entscheidende Code: coding. :roll:

Wieso?
Zitat:

Zitat von Rawsche (Beitrag 1410658)
Delphi-Quellcode:
procedure TForm1.Coding(var x:string);
var i:integer;
begin
  for i:=0 to listbox1.items.count-1 do
  if x=listbox1.items[i] then x:=listbox2.items[i];
end;


Uwe Raabe 14. Aug 2018 21:21

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
OK, hier läuft was falsch:
Zitat:

Zitat von Rawsche (Beitrag 1410658)
Delphi-Quellcode:
      for i:=1 to Length(Memo1.lines.text) do
      begin
        x:=coding(memo1.lines.Strings[i]);
        memo2.lines.Strings[i]:=x;
      end;

Delphi-Quellcode:
Memo1.Lines.Text
gibt den gesamten Text inklusive Zeilenumbrüche zurück.
Delphi-Quellcode:
Memo1.lines.Strings[i]
gibt aber die i-te Zeile zurück und nicht das i-te Zeichen.

Weiterhin
  • erwartet coding einen variablen string, bekommt aber ein string-Property
  • coding gibt keinen Rückgabewert, weswegen man es auch nicht einem x zuweisen kann

Luckie 14. Aug 2018 22:01

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1410665)
Zitat:

Zitat von Luckie (Beitrag 1410659)
Und wieder fehlt der entscheidende Code: coding. :roll:

Wieso?
Zitat:

Zitat von Rawsche (Beitrag 1410658)
Delphi-Quellcode:
procedure TForm1.Coding(var x:string);
var i:integer;
begin
  for i:=0 to listbox1.items.count-1 do
  if x=listbox1.items[i] then x:=listbox2.items[i];
end;


Ups. Ich hatte eine Methode gesucht, die was mit einem String "macht", eben codiert, wie auch imner, und nicht irgendwelchen Code der was mit VCL Steuerelementen macht. :roll:

KodeZwerg 14. Aug 2018 22:13

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Zitat:

Zitat von Rawsche (Beitrag 1410658)
Ich freue mich auf eure Ideen. Bitte berichtigt NICHT einfach den Code, sondern gebt mir vielleicht lieber Tipps, wie ich ihn selbst verbessern kann. Sonst lerne ich daraus leider nichts...

Ich würde, sobald Dein visuell Nachvollziehbares Produkt soweit funktioniert das Du Verstanden hast Wie & Wieso es nun funktioniert folgendes Vorschlagen:
Steige von ListBoxen für Deine Umwandlung auf zum Beispiel ein Array oder Set um. Auf diese Weise blendest Du für andere aus woraus Deine Umwandlung basiert / non-Visuell sozusagen.

Rawsche 15. Aug 2018 12:39

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Schonmal Vielen Dank

API 15. Aug 2018 13:34

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
...

Rawsche 15. Aug 2018 13:51

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Hi,

bis auf ein kleines Problem habe ich Fortschritte gemacht. Ich bin auf Funktionen umgestiegen. Der Text lässt sich umwandeln und auch wieder zurückwandeln.

Ein Problem tritt nur auf. Bei mir wird in der Verschlüsselung jedes Leerzeichen durch ein ß ersetzt. Jedes ß wird zum Leerzeichen.
Bei der Entschlüsselung ist es umgekehrt. Soweit alles geplant.

Leider tritt bei jeder Umwandlung von einem ß ein Fehler auf. Das ß wird nicht durch ein Leerzeichen ersetzt, sondern es bleibt ein ß, egal ob Ver- oder Entschlüsselung. Kann es sein, dass ein ß nicht mit einem ß verglichen werden kann oder dass ein bestehendes ß nicht durch ein Leerzeichen ersetzt werden kann?

Vielen Dank


Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids,
  StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    ListBox1: TListBox;
    ListBox2: TListBox;
    Memo1: TMemo;
    Memo2: TMemo;
    Memo3: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    function Coding(x: string): string;
    function Decoding(x: string): string;

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function TForm1.Coding(x: string): string;
var
  i: integer;
  y: string;
begin
  y := x;
  for i := 0 to listbox1.items.Count - 1 do
  begin
    if x = listbox1.items[i] then
    begin
      y := listbox2.items[i];
    end;
  end;

  Result := y;
end;

function TForm1.Decoding(x: string): string;
var
  i: integer;
  y: string;
begin
  y := x;
  for i := 0 to listbox2.items.Count - 1 do
  begin
    if x = listbox2.items[i] then
    begin
      y := listbox1.items[i];
    end;
  end;

  Result := y;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  i2: integer;
  x: string;
begin
  label2.Caption := '';
  memo2.Clear;
  for i := 0 to (Memo1.Lines.Count - 1) do
  begin
    label1.Caption := memo1.Lines.strings[i];
    for i2 := 1 to length(label1.Caption) do
    begin
      x := label1.Caption[i2];
      x := coding(x);
      label2.Caption := label2.Caption + x;

    end;
    memo2.Lines[i] := (label2.Caption);
    label2.Caption := '';
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
  i2: integer;
  x: string;
begin
  label2.Caption := '';
  memo3.Clear;
  for i := 0 to (Memo2.Lines.Count - 1) do
  begin
    label1.Caption := memo2.Lines.strings[i];
    for i2 := 1 to length(label1.Caption) do
    begin
      x := label1.Caption[i2];
      x := decoding(x);
      label2.Caption := label2.Caption + x;

    end;
    memo3.Lines[i] := (label2.Caption);
    label2.Caption := '';
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if edit1.text='ß' then showmessage('');
end;

end.

Delphi.Narium 15. Aug 2018 14:00

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Zitat:

Zitat von himitsu (Beitrag 1410634)
@Delphi.Narium:
Falsch, Memo1.Lines.Text ist schneller, denn Delphi (und bestimmt auch Lazarus) leiten das direkt an das Memo und holen den kompletten Text mit Einmal ab oder weisen ihn direkt zu,
genau so wie bei Memo.Text

Der Zugriff auf Einzelzeilen (Lines[]) ist langsam, vor allem beim Ändern und wenn viel Text im Memo steht.

Ja, aber das Zusammenbauen des Inhaltes von Text dauert ggfls. sehr lange. (Zumindest bei älteren Delphis). Meine praktische Erfahrung ist, dass das zeilenweise Ändern deutlich schneller ist, als erst Text "zusamenbauenzulassen", dann dadrin zu ändern und anschließend bei der Zuweisung zu Text wieder "allesauseinandernehmenzulassen".

Wenn man sich mal die Sourcen (Delphi 7) von function TStrings.GetTextStr: string;, welches beim Lesen von Text aufgerufen wird, anschaut, so wird dort bereits eine Schleife for I := 0 to Count - 1 do aufgerufen.
Und bei SetTextStr (zum Schreiben von Text), wird der übergebene String an den Zeilenumbrüchen aufgeteilt. Vorher wird Lines (vom Typ TStrings) geleert und dann jede der getrennten Zeilen per Add an die Lines angefügt.

Dies erspare ich mir bei meiner Vorgehensweise. Und niemand kann mir ernsthaft weißmachen, dass diese Ersparnis = 0 ist. Jedenfalls sind meine Programme, die häufig mit TStrings (bzw. entsprechenden Nachfahren) und recht großen Texten arbeiten, ausnahmslos alle (nach dieser Änderung) deutlich schneller geworden.

himitsu 15. Aug 2018 14:46

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Ich sehe garkeinen Code, der irgendwo die ß übersetzt, demnach wäre es verständlich, wenn das auch nicht gemacht wird. :stupid:


PS: Du gehst doch die Items "manuell" durch und vergleichst jeden Text einzeln.
Du könntest aber auch suchen lassen, mit einem Befehl ala ListBox1.Items.IndexOf und kannst bei >=0 das gewünschte Item aus der anderen Listbox auslesen.


Zitat:

Zitat von Delphi.Narium (Beitrag 1410738)
Ja, aber das Zusammenbauen des Inhaltes von Text dauert ggfls. sehr lange. (Zumindest bei älteren Delphis). Meine praktische Erfahrung ist, dass das zeilenweise Ändern deutlich schneller ist, als erst Text "zusamenbauenzulassen", dann dadrin zu ändern und anschließend bei der Zuweisung zu Text wieder "allesauseinandernehmenzulassen".

Theoretisch ja, ABER

bei der normalen StringList wird im .Text der Text aus allen Zeilen erst zusammengesetzt,
wenn das TMemoStrings (der spezielle TStrings-Nachfahre im TMemo) das ebenfalls machen würde, also alle Zeilen einzeln abfragen und zusammensetzen, dann wäre es wirklich "extrem" langsam.

Aber das MEMO verwaltet intern den ganzen Text als einen Block im Speicher, weswegen im TMemo das Lines.Text überschrieben wurde und somit das Gleiche wie Memo.Text macht, also den kompletten Text mit nur einer Abfrage ausliest und auch zuweist.

p80286 15. Aug 2018 21:05

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Delphi-Quellcode:

type

   { TForm1 }

   TForm1 = class(TForm)
     Button1: TButton;
     Button2: TButton;
     Label1: TLabel;
     Label2: TLabel;
     ListBox1: TListBox;
     ListBox2: TListBox;
     Memo1: TMemo;
     Memo2: TMemo;
     Memo3: TMemo;
     procedure Button1Click(Sender: TObject);
     procedure Button2Click(Sender: TObject);
     procedure Button3Click(Sender: TObject);
   private
     function Coding(x: string): string;
     function Decoding(x: string): string;

   public

   end;

procedure TForm1.Button3Click(Sender: TObject);
begin
   if edit1.text='ß' then showmessage('');
end;

end.
Ich hab Deinen Source mal auf das absolut notwendige zusammen gestrichen.
Das kann nicht kompilieren, geschweige denn ein "ß" in " " übersetzen.

Gruß
K-H

haentschman 16. Aug 2018 06:10

AW: Zeichen in Memo ersetzten und Formatierung beibehalten?!
 
Moin...:P
Delphi-Quellcode:
function TForm1.Coding(x: string): string;
var
  i: integer;
  y: string;
begin
  y := x;
  for i := 0 to listbox1.items.Count - 1 do
  begin
    if x = listbox1.items[i] then
    begin
      y := listbox2.items[i];
    end;
  end;

  Result := y;
end;
...bitte verwende sprechende Namen. Aus eigener Erfahrung: Je kompexer die Anwendung...dann weißt du in 3 Monaten nicht mehr was was ist. :zwinker:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:52 Uhr.

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