Code:
[b]function[/b] spiegeln(p: PChar): PChar;
[b]var[/b] test: [b]string;
begin[/b]
test := [b]string[/b](p);
...
Result := PChar(test);
[b]end[/b];
Um dir mal zu erklären, warum das nicht funktioniert:
Dein Programm ruft spiegeln(PChar(MyString)) auf, dabei wird PChar(MyString) auf dem sog. Stack abgelegt und
p zeigt auf die Speicherstelle im Stack, an der PChar(MyString) liegt. (Danach kommt noch die Rücksprungadresse auf den Stack.)
Nun wird Platz auf dem Stack für die lokale Variable
test gemacht. In diese kopierst du den PChar, auf den
p zeigt und führst deine Umkehrung durch.
Bis jetzt funktioniert alles, doch nun kommt der entscheidende logische Fehler:
Du weist
Result nun einen Zeiger (PChar ist ja nur ein Zeiger) auf die Speicheradresse, an der
test abgelegt ist, zu. Doch da
test eine lokale Variable ist und somit auf dem Stack liegt, zeigt
Result auf eine Adresse im Stack.
Durch das
end; wird nun aber der von
test belegte Stack-Speicher freigegeben, womit
Result auf einen bereits freigegebenen Speicherbereich zeigt. Wenn nun ein weiterer Funktionsaufruf nach dem Zurückkehren der spiegeln-Funktion stattfindet (es reicht auch eine einfache Zuweisung von Variablen), dann überschreibt diese die noch auf dem Stack an der
Result-"Adresse" liegenden, unveränderten Bytes mit ihren eigenen lokalen Variablen und Parametern.
Deswegen liefert die Funktion nur noch Bytesschrott zurück, der auch noch zum teilweise auch noch aus den "orignal"-Daten bestehen kann (was die Fehlersuche dann eher auf die Funktion selbst ziegt).
Das Problem könntest du z.B. so lösen, dass du den String "in-place" spiegelst (also Eingabe-Parameter = Ausgabe-Parameter):
Code:
[b]procedure[/b] spiegeln(p: PChar);
[b]var[/b] s: [b]string[/b];
[b]begin[/b]
s := p;
...
StrLCopy(p, PChar(s), StrLen(p)); // Daten in p zurückschreiben
[b]end[/b];
s := 'Dies ist ein Test';
spiegeln(PChar(s));
ShowMessage(s);
Das in-place-Verfahren funktioniert nur, wenn die Länge der Eingabedaten mit der der Ausgabe-Daten übereinstimmt.
Oder um es
WinAPI gerecht zu machen:
Code:
[b]function[/b] spiegeln(p: PChar; Buffer: PChar; MaxBufferLen: Integer): Integer;
[b]var[/b] s: [b]string[/b];
[b]begin[/b]
s := p;
...
[b]if[/b] Buffer <> [b]nil then[/b]
StrLCopy(Buffer, PChar(s), MaxBufferLen); // Daten in Buffer schreiben
Result := Length(s); // Rückgabewert = Länge des bearbeiteten Strings
[b]end[/b];
[b]var[/b]
Buf: PChar;
BufSize: Integer;
[b]begin[/b]
s := 'Dies ist ein Test';
BufSize := spiegeln(PChar(s), nil, 0);
Buf := StrAlloc(BufSize);
[b]try[/b]
spiegeln(PChar(s), Buf, BufSize);
[b]finally[/b]
StrDipose(Buf);
[b]end[/b];
ShowMessage(s);
[b]end[/b];
[i]// Wenn die max. Aufgabelänge bekannt ist, dann geht das auch so:[/i]
[b]var[/b] Buf: [b]array[/b][0..1024] [b]of[/b] Char;
SetString(s, Buf, spiegeln(PChar(s), Buf, 1024));
ShowMessage(s);
Ein function Xyz: PChar; sollte man nur verwenden, wenn man konstante oder global deklarierte Strings einsetzt. Konstante Strings sind nur Strings, die in '' stehen. Wenn ein
+ oder ein Funktionsaufruf notwendig sind, dann handelt es sich nicht um konstante Strings, da sie erst zur Laufzeit zusammengesetzt werden müssen. Am einfachsten kann man herausbekommen, ob ein String konstant ist oder nicht, indem man sich selbst nur Fragen muss, könnte man diesen String auch so deklarieren:
const MyString = 'Hier steht der zu "prüfende" String';