Autor Beitrag
oPPi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: So 20.10.02 02:48 
Hallo,

Ich hab von meinem Dotzenten ne Aufgabe hingeschnissen bekommen die mir einiges Kopfzerbrechen :roll: bereitet.
Ich habe ein RichEdit1, RichEdit2, Button_Codiere, Button_Decodiere.

Jetzt zu meinen Problem:
Ich gebe Text in das RichEdit1 ein, dieser soll dann wenn ich den Button_Codiere betätige verschlüsselt werden nach dem Schlüssel:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <- Klartext
Q A Y W S X E D C R F V T G B Z H N U J M I K O L P <- Geheimtext
(Diese Methode nennt sich Monoalphabetische Chiffrierung)

Ich hab das mal getestet mit der Function:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
function Search_And_Replace(RichEdit: TRichEdit; 
  SearchText, ReplaceText: string): Boolean; 
var 
  startpos, Position, endpos: integer; 
begin 
  startpos := 0; 
  with RichEdit do 
  begin 
    endpos := Length(RichEdit.Text); 
    Lines.BeginUpdate; 
    while FindText(SearchText, startpos, endpos, [stMatchCase])<>-1 do 
    begin 
      endpos   := Length(RichEdit.Text) - startpos; 
      Position := FindText(SearchText, startpos, endpos, [stMatchCase]); 
      Inc(startpos, Length(SearchText)); 
      SetFocus; 
      SelStart  := Position; 
      SelLength := Length(SearchText); 
      richedit.clearselection; 
      SelText := ReplaceText; 
    end; 
    Lines.EndUpdate; 
  end; 
end;

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.Button_VerschluesselnClick(Sender: TObject); 
begin
  RichEdit2.Text := RichEdit1.Text; 
  Search_And_Replace(Richedit1, 'OldText', 'NewText');
  MsgBox('Der Text wurde verschlüsselt !!!'); 
end;


Das funktioniert auch soweit wenn ich für OldText u. NewText die entsprechenden Werte (siehe oben) einsetze. Oder gibt es da ne bessere
Lösung?

Der verschlüsselte Text soll mir dann im RichEdit2 ausgegeben werden.
Wenn ich den Button_Decodiere betätige soll mir der verschlüsselte Text wieder als Klartext im RichEdit1 ausgeben werden.

Ich wäre euch für eine schnelle Hilfe sehr verbunden.
Gruß
oPPi
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 20.10.02 05:36 
Ich muß gestehen, ich habe mir da jetzt keinen großen Kopf gemacht, aber als erstes ist mir [StringReplace[/b] durch den Kopf geschwirrt. Mir dem Flag ReplaceAll sollte es eigentlich kein Problem sein.
Wolff68
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: So 20.10.02 21:01 
Wird nicht hinhauen Luckie.
Wenn er alle A durch Q ersetzt und später alle Q zu H ist das Chaos Perfekt...

Eine Lösung wäre es in zwei Durchläufen. Erst A durch Ord(Q)+128 ersetzen usw... dann alles wieder runtersetzen.
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
const Ursprung   = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const Schluessel = 'qaywsxedcrfvtgbzhnujmikolpQAYWSXEDCRFVTGBZHNUJMIKOLP';
....
procedure TForm1.Button1Click(Sender: TObject);
var i : byte;
    puffer : string;
begin
  puffer := Memo1.Text;
  For i := 1 to Length(Ursprung) do begin
    puffer := StringReplace(puffer,
                            Ursprung[i],
                            Chr(Ord(Schluessel[i])+128),
                            [rfReplaceAll]);
  end;
  For i := 1 to Length(Ursprung) do begin
    puffer := StringReplace(puffer,
                            Chr(Ord(Schluessel[i])+128),
                            Schluessel[i],
                            [rfReplaceAll]);
  end;
  Memo2.Lines.Clear;
  Memo2.Text := puffer;
end;

Zurück das ganze dann genauso.

Ein Problem gibt es dabei aber, wenn im Text Zeichen sind, die aus dem oberen ASCII-Bereich sind. In diesem Beispiel wird ein ä nach dem zurückübersetzen zu einem h :?

_________________
"Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
oPPi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: So 20.10.02 22:13 
Hallo,

@Wolff68:

Die Umlaute wie ä,ü,ö und Sonderzeichen aus der oberen ASCII-Tabelle werden nicht verwendet. Es geht nur um die von mir angegebenen Zeichen.

Ich werd deinen Code mal checken ob er für meine Bedürfnisse reicht -> ich hoffe es zu mindest. So wie ich das überblicken kann, macht es nen ganz Guten :lol:

Werd mich morgen nochmal melden ob's gereicht hat fürn Bienchen :wink:

Gruß

oPPi
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 20.10.02 22:28 
Hi!

Geht's nicht auch so? Oder habe ich eine Anforderung an den Code übersehen? (Code kodiert, dekodieren geht dann halt genau andersrum)

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
const Ursprung   = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const Schluessel = 'qaywsxedcrfvtgbzhnujmikolpQAYWSXEDCRFVTGBZHNUJMIKOLP';

{...}

procedure TForm1.Button1Click(Sender: TObject);
VAR i,position : INTEGER;
begin
  memo2.text:='';
  for i:=1 TO Length(memo1.Text) do
  begin
    position:=Pos(memo1.Text[i],ursprung);
    if position>0 then memo2.text:=memo2.text+schluessel[position]
    else memo2.text:=memo2.Text+memo1.text[i];
  end;
end;


MfG,
Peter

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
oPPi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: So 20.10.02 23:09 
Hallo,

@Peter Lustig
dein Code ist super - die Sonderzeichen werden normal dargestellt das ist zwar nebensächlich aber man kann halt auch diese dann verwenden.

Anders herum sieht das ganze dann so aus:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button2Click(Sender: TObject);
VAR i,position : INTEGER;
begin
  memo1.text:='';
  for i:=1 TO Length(memo2.Text) do
  begin
    position:=Pos(memo2.Text[i],Schluessel);
    if position>0 then memo1.text:=memo1.text+Ursprung[position]
    else memo1.text:=memo1.Text+memo2.text[i];
  end;
  Memo2.Lines.Clear;
end;

Ich hab jetzt einige Foren durchforstet aber bislang nichts passendes gefunden.
Aber hier werden Sie geholfen ... :lol:
Ist vielleicht auch für andere User interessant ...

Gruß

oPPi

PS: @Wolff68 - Deine Bio auf deiner Website find ich interessant, haben fast die gleichen Daten nur das ich "1101" Month jünger bin.

_________________
... Manchmal kommt man nicht auf die einfachsten Sachen obwohl
die Lösung ganz nah liegt ...
Wolff68
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: So 20.10.02 23:41 
Und wiedermal muß ich Peter recht geben. Ist sicherer wegen den Umlauten.

Das mit dem einzeln durchgehen der Zeichen ist auch das naheliegende, nur hab ich schon oft bemerkt, daß das recht langsam ist. Pos() und StringReplace() sind da irgendwie schneller durch.
Meine Schleifen laufen nur 2x von a bis Z und fertig.

_________________
"Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.10.02 01:47 
Wolff68 hat folgendes geschrieben:
Wird nicht hinhauen Luckie.
Wenn er alle A durch Q ersetzt und später alle Q zu H ist das Chaos Perfekt...

Ich sagte, ja das ist mir so spontan durch den Kopf geschossen.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.10.02 08:33 
Mir ist spontan der HTML-Parser von other durch den Kopf geschossen. Damit gehst du in einem Durchgang durch den Text durch, hast aber die Möglichkeit, gezielt auf einzelne Zeichen (Chars) zu kontrollieren.

Das heißt, ist aus dem A erst mal ein Q geworden, springt er zum nächsten Zeichen, und das Chaos sollte nicht auftreten.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.10.02 09:49 
Hier mal mein Vorschlag - wie gesagt, auf der technischen Basis von others HTML-Parser. Der kommt ohne "pos" und "StringReplace" aus und ist auch bei größeren Texten recht flott.
Luckie wird´s vielleicht wissen, die anderen dürfen mir glauben ... :)
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
function CodeFunc(const szInString: AnsiString): AnsiString;
const
  encodetable : string[26] = 'QAYWSXEDCRFVTGBZHNUJMIKOLP';
var
  pSrc,
  pResult     : pchar;
  lc          : char;
begin
  SetLength(Result,0);
  if(length(szInString) = 0) then exit;

  pSrc := pointer(szInString);
  if(pSrc = nil) or (pSrc^ = #0) then exit;

  SetLength(Result,length(szInString));
  pResult := pointer(Result);
  ZeroMemory(pResult,length(szInString));

  while(pSrc^ <> #0) do
    begin
      case pSrc^ of
        'A'..'Z':
          Move(encodetable[(byte(pSrc[0]) - 64)],pResult^,1);
        'a'..'z':
          begin
            lc := CHR(byte(encodetable[byte(pSrc[0]) - 96]) + 32);
            Move(lc,pResult^,1);
          end;
        else
          Move(pSrc[0],pResult^,1);
      end;

      inc(pResult);
      inc(pSrc);
    end;
end;

Zur Erklärung -
Der Buchstabe A hat ja bekanntlich den ASCII-Wert 65. Da auch in der ASCII-Tabelle die Buchstaben des Alfabets aufeinanderfolgen, können wir die passenden Schlüsselwerte in einem String der Reihe nach anordnen:
ausblenden Quelltext
1:
2:
const
  encodetable : string[26] = 'QAYWSXEDCRFVTGBZHNUJMIKOLP';

Bleiben wir beim Beispiel mit dem Buchstaben A -
Um nun an den passenden Codewert zu kommen, ziehen wir 64 ab
ausblenden Quelltext
1:
A (65) - 64 = 1					

Diesen Wert Eins benutzen wir in der Anweisung:
ausblenden Quelltext
1:
Move(encodetable[(byte(pSrc[0]) - 64)],pResult^,1);					

um das entsprechende Zeichen in "encodevar", das sich an dieser Position befindet, in das Ergebnis (= den Rückgabewert der Funktion) zu kopieren. Und das erste Zeichen unseres Strings ist ein Q.
Und so fort: B hat den ASCII-Wert 66, minus 64 ergibt 2, das entspricht dem A im String ... 8)

Bei den Kleinbuchstaben ist das Prinzip identisch, nur ist hier der Wert, den wir abziehen müssen, 96. Das kleine A hat ja den ASCII-Wert 97, und wir müssen ja wieder auf unsere erste Position kommen. Richtig? Gut, da wir dann aber einen Großbuchstaben haben, müssen wir dessen ASCII-Wert heranziehen und 32 addieren.
Wieder am Beispiel des A:
ausblenden Quelltext
1:
2:
a (97) - 96 =   1 (entspr. dem Q im String)
Q (81) + 32 = 113 (entspr. dem ASCII-Wert von q)

wzbw.

Ein Wort noch dazu:
ausblenden Quelltext
1:
2:
else
  Move(pSrc[0],pResult^,1);

oPPi hat zwar gesagt, es werden nur die Buchstaben des Alfabets genutzt. Man sollte aber dennoch damit rechnen, dass mal ein anderes Zeichen angegeben wird. Also reichen wir alles, was durch unser Raster (A-Z,a-z) fällt, 1:1 an das Funktionsergebnis durch.

Für die Dekodierung können wir übrigens die selbe Funktion verwenden. Lediglich die Stringtabelle (var "encodestring") wäre durch diese hier:
ausblenden Quelltext
1:
'BOIHGKNQVTWYURXZAJEMSLDFCP';					

zu ersetzen. Ich empfehle aber, eine zweite Variable (var "decodetable") mit diesem Inhalt anzulegen und im Funktionskopf eine Bool-Variable zu ergänzen, die über Kodierung und Dekodierung entscheidet. Beispielsweise:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function CodeFunc(const szInString: AnsiString;
  const Encode: boolean): AnsiString;
const
  encodetable : string[26] = 'QAYWSXEDCRFVTGBZHNUJMIKOLP';
  decodetable : string[26] = 'BOIHGKNQVTWYURXZAJEMSLDFCP';
{ ... }
        'A'..'Z':
          if(Encode) then Move(encodetable[(byte(pSrc[0]) - 64)],pResult^,1)
            else Move(decodetable[(byte(pSrc[0]) - 64)],pResult^,1);

        'a'..'z':
          begin
            if(Encode) then lc := CHR(byte(encodetable[byte(pSrc[0]) - 96]) + 32)
              else lc := CHR(byte(decodetable[byte(pSrc[0]) - 96]) + 32);
            Move(lc,pResult^,1);
          end;
{ ... }

Das war´s.