Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - zwei Zeichen per XoR miteinander verknüpfen


Bomania - So 16.02.03 11:04
Titel: zwei Zeichen per XoR miteinander verknüpfen
Hallo,

ich möchte zwei Zeichen per XoR miteinander verknüpfen und das Ergebnis als ASCII-Zeichen ausgeben. So wie hier funktioniert es einwandfrei:

Quelltext
1:
chr(ord('D') xor ord('t'));  //Ergebnis = 0 (#48)                    

Wenn es sich jetzt aber um String-Variablen handelt, weil ich mehrere Zeichen nacheinander miteinander verknüpfen möchte, dann funktioniert die Sache nicht:


Quelltext
1:
2:
3:
// str1 = 'Hallo', str2 = 'Test'
// per For-Schleife wird jeweils um eine Position in i und i2 weitergegangen
chr(ord(str1[i]) xor ord(str2[i2]));

Dann habe ich es so versucht:

Quelltext
1:
chr(ord(copy(str2,i,1) xor ord(copy(str1,ipos,1)));                    

Hier erscheint die Fehlermeldung "Inkompatible Typen"

Ich weiß langsam echt nicht mehr weiter. Was unter VB mit 10Min Aufwand funktioniert hat, kriege ich unter Delphi nicht mal in 2 Tagen hin. Dabei ist Delphi doch eigentlich in vielen Dingen leichter zu handhaben als mit anderen PS.

Kann mir da jemand helfen? Was habe ich oben falsch gemacht? :(

Moderiert von user profile iconTino: Titel geändert.


BungeeBug - So 16.02.03 11:10

darf man fragen was du vor hast?

MfG BungeeBug


Bomania - So 16.02.03 11:26

Das habe ich oben ja bereits versucht zu erklären. Aber ich versuche es nochmal deutlicher zu beschreiben.

Ich habe zwei Variablen:

str1 := 'Hallo';
str2 := 'Text der mit str2 vernüpft werden soll';

Diese möchte ich per XoR verknüpfen (hier im Pseudocode):

'T' XoR 'H' (= irgendein anderes Zeichen)
'e' XoR 'a' (= irgendein anderes Zeichen)
usw...

Ist das Ende von str1 erreicht, fängt es wieder von vorne an (also 'H'). Auf diese weise möchte ich einen kompletten Text der in str2 gespeichert ist mit str1 verknüpfen. Das geschieht mit einer For-do-Schleife.

Um das nochmal praktisch zu zeigen, hier die entsprechende Stelle:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
intStr1Len := Length(str1);
ipos := 1;
For i := 1 To Length(str2) do
    begin
      If ipos > intStr1Len Then
      begin
        ipos := 1;
      end; //if

    txt_Text.text:=txt_Text.text + chr(ord(str2[i]) xor ord(str1[ipos]));
    ipos := ipos + 1;
  end; //for


Edit: Als Ergebnis sollte dann ein Text herauskommen, der genausoviele Zeichen hat wie str2. Das ist aber nicht der Fall. Irgendwie ist da der Wurm drin.

Edit2: Ich habe es nochmal überprüft - die XoR-Verknüpfung funktioniert. Das Problem liegt an der Chr()-Funktion. Als Ergebnis bekomme ich bis auf das erste Zeichen nur schwarze Blöcke.


Bomania - So 16.02.03 14:04
Titel: Problem liegt wo ganz anders
Das gibts ja nicht, das Problem liegt wo ganz anders. Nach ewigen Tests habe ich heraus gefunden, dass die Schleife wohl abbricht, sobald zufällig ein Zeichen von str1 auf ein identisches Zeichen von str2 'trifft' (z.B. 't' auf 't'). Das kann ich mir nun wirklich nicht erklären. Habt ihr ne Idee?


DaRkFiRe - So 16.02.03 14:34

t XOR t = 0
t XOR 0 = t
0 XOR t = t
0 XOR 0 = 0

nehmt das t jetzt bitte mal als Buchstabe, der gedanklich in einen ASCII-Code übersetzt wird

Und wie wir alle wissen, wird ein Speicherstring (ein PChar) mit einem #0 terminiert, soweit nicht anders vereinbart (GetMem, z.B.)


Sollte es eine Verschlüsselungsprozedur werden, rate ich zu folgendem Code:

es sei S1 der Ursprungs-String, S2 das "Passwort"

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var S1,S2,S3:STRING;
var I:INTEGER;
...
S3:=STRINGOFCHAR(#0,LENGTH(S1));
for I:=1 TO LENGTH(S1) do
  begin
    S3[I]:=BYTE(S1[i]) XOR BYTE(S2[((I-1) MOD LENGTH(S2))+1]);
  end;

//das Ergebnis ist in S3


Bomania - So 16.02.03 14:51


Quelltext
1:
S3[I]:=BYTE(S1) XOR BYTE(S2[((I-1) MOD LENGTH(S2))+1]);                    


In dieser Zeile bekomme ich eine Fehlermeldung "Ungültige Typumwandlung" und eine Warnung "Vorzeichenbehaftete und -lose Typen werden kombiniert"


DaRkFiRe - So 16.02.03 15:39


Quelltext
1:
S3[I]:=BYTE(S1[i]) XOR BYTE(S2[((I-1) MOD LENGTH(S2))+1]);                    


Aufmerksame im-Kopf-vor-Kompilierer haben es sicher schon gemerkt:

S3[I] ist vom Typ char

Richtig müsste es ungefähr so gehen:

Quelltext
1:
S3[I]:=CHR(BYTE(S1[i]) XOR BYTE(S2[((I-1) MOD LENGTH(S2))+1]));                    


Brueggendiek - Mo 17.02.03 03:17
Titel: Re: zwei Zeichen per XoR miteinander verknüpfen
Hallo!

So
Bomania hat folgendes geschrieben:

Quelltext
1:
chr(ord(copy(str2,i,1) xor ord(copy(str1,ipos,1)));                    

Hier erscheint die Fehlermeldung "Inkompatible Typen"

kann das ja nicht gehen! Copy(quelle, start, laenge) ist ein String, Ord erwartet ein Zeichen!
Innerhalb der Länge der Strings (WICHTIG!) muß man schreiben:

Quelltext
1:
chr(ord(str2[i]) xor ord(str1[ipos]));                    

dann geht das!
Es muß nur sichergestellt sein, daß i und ipos nicht kleiner als 1 und nicht größer als die Länge des Strings sind!

Gruß

Dietmar Brüggendiek


BungeeBug - Mo 17.02.03 13:44
Titel: Re: Problem liegt wo ganz anders
Bomania hat folgendes geschrieben:
Das gibts ja nicht, das Problem liegt wo ganz anders. Nach ewigen Tests habe ich heraus gefunden, dass die Schleife wohl abbricht, sobald zufällig ein Zeichen von str1 auf ein identisches Zeichen von str2 'trifft' (z.B. 't' auf 't'). Das kann ich mir nun wirklich nicht erklären. Habt ihr ne Idee?


Ja kann ich das "XOR" is das "exclusive OR" was soviel heisst wie ausschliesendes oder

Quelltext
1:
2:
3:
4:
5:
6:
 a | b | c |
------------
 0 | 0 | 0 |
 0 | 1 | 1 |
 1 | 0 | 1 |
 1 | 1 | 0 |

also das "wirkt" nur wenn die beiden Variablen verschieden sind ...
das was du warscheinlich suchst is das normale "OR"

Quelltext
1:
2:
3:
4:
5:
6:
 a | b | c |
-------------
 0 | 0 | 0 |
 0 | 1 | 1 |
 1 | 0 | 1 |
 1 | 1 | 1 |


P.S.: A = Eingang 1 also ne Variable
B = Eingang 2 also auch ne Variable
C = Ausgang 1 also on jetzt true oder false

MfG BungeeBug


Bomania - Fr 21.02.03 09:53

Danke für die Nachhilfe, aber die Funktionsweisen von XoR, Or und AND sind mir bereits vertraut (sonst würde ich mit diesen Verknüpfungsoperationen wahrscheinlich gar nicht arbeiten). Das Problem ist mittlerweile gefunden: das Memo ist dran schuld. Denn es terminiert bei #0. Und #0 entsteht jedesmal wenn man zwei identische Zeichen mit XoR miteinander verknüpft. Das muss man anscheinend so hinnehmen, denn das Memo zeigt den Text nur bis zum ersten #0.


HeLe - So 02.03.03 11:16

Bomania hat folgendes geschrieben:
Das Problem ist mittlerweile gefunden: das Memo ist dran schuld. Denn es terminiert bei #0. Und #0 entsteht jedesmal wenn man zwei identische Zeichen mit XoR miteinander verknüpft. Das muss man anscheinend so hinnehmen, denn das Memo zeigt den Text nur bis zum ersten #0.


Das Memofeld ist nicht daran schuld, das ist ganz einfach eine Eigenschaft von nullterminierten Strings wie sie Delphi (und auch C/C++) benutzt. Das Ende eines solchen Strings wird eben durch das Nullzeichen angezeigt - das ist halt so. Das alte Pascal (und anscheinend auch VB - aber damit kenn ich mich nicht aus) benutzt ne andere Technik: Da wird im 1. Byte die Länge des Strings gespeichert, mit dem Effekt, das so ein String nur 255 Zeichen enthalten kann. Deswegen - und um kompatibel zu C-Funktionen (wie z.B. die aus der Windows-API) zu werden - sollten diese Strings in Delphi nicht mehr verwendet werden, du kannst sie aber noch benutzen wenn du den Datentyp shortstring verwendest (damit kommen dann allerdings die Komponenten nicht klar, weswegen dir das wohl wenig helfen wird)


DaRkFiRe - So 02.03.03 14:39

Hallo HeLe!

Du bist aber ganz dolle im Irrtum, ganz ganz dolle.

Denn Memo is nix weiter als ein vordefiniertes Windows-Control (Delphi kapselt nur die Messages an das Fenster) und da Windows intern mit Zeigern arbeitet (wer tut das nicht!?), ist, wenn man einen Zeiger übergibt, bei #0 Schluss.

Weise bitte mal einem String (AnsiString - also als STRING deklariert) folgendes zu (Du deklarierst ihn mal als globale Variable):


Quelltext
1:
S:=STRINGOFCHAR(#0,7);                    


Dann gib den String mal im Formular-Titel (Caption) aus (meinetwegen in OnCreate):


Quelltext
1:
Form1.Caption:=S;                    


Er zeigt nichts an! Warum??? WINDOWS arbeitet intern mit Zeigern, die bei #0 terminieren.

Jetzt gib doch mal an ihrendeiner Stelle im Programm die Länge des Strings aus - es wird 7 sein, Delphi (hoho!?) terminiert INTERN nicht bei #0!!!
Womit nicht Delphi, sondern Windows daran schuld ist.

Alle Klarheiten beseitigt!?


HeLe - So 02.03.03 17:16

s.u.


HeLe - So 02.03.03 17:28

oops, stimmt :oops: , dann speichert Delphi bei ansistrings doch die Länge. Naja, das nützt einem auf jeden Fall nicht viel, da man bei der Ausgabe normalerweise um die Windows-API nicht drumrumkommt.
Es ist aber kein "Fehler", da die Windows-API-Funktionen in C programmiert sind, das ist eigentlich alles was ich sagen wollte. :lol: