Type Casting String to Integer mit Unicode

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
markkowalt
Beiträge: 32
Registriert: Sa 13. Aug 2011, 16:15

Type Casting String to Integer mit Unicode

Beitrag von markkowalt »

Hallo,

wie kann man einen String nach Integer casten ?

Nicht StrToInt, damit wird der String ja nur als Integer dargestellt mit dem numerischen Wert der gegebenen Zahl.

Ich habe Lazarus v1.0.4 für Windows (wohl nicht so wichtig) und FPC 2.6.0 mit der Bezeichnung "fpc\2.6.0\bin\x86_64-win64", also für 64bit-System.

Ich glaube, dass das unter win 32bit einfach mit

Code: Alles auswählen

stringval := 'blabla';
intval := integer(stringval); // da ist jetzt der string gecastet, genau da gibts nen Fehler siehe unten
showmessage( inttostr(intval) ); // nur zum Ausgeben
Fehlermeldung:
Error: Illegal type conversion: "Constant String" to "LongInt" // wenn ich den string direkt reinschreibe, also integer('irgendwas')
Error: Illegal type conversion: "AnsiString" to "LongInt" // siehe beispiel

Ja, wer kann mir also helfen??

Danke schonmal

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2805
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Type Casting String to Integer mit Unicode

Beitrag von m.fuchs »

Du kannst nur Typen casten, die auch ineinander umwandelbar sind. Char zu Integer würde zum Beispiel gehen. Aber AFIAK keinen String in einen Integer.

Was möchtest du denn erreichen?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

e445697
Beiträge: 11
Registriert: Fr 22. Jun 2012, 11:46

Re: Type Casting String to Integer mit Unicode

Beitrag von e445697 »

Ich möchte, wer es kennt : ähnlich wie "Cheat Engine", den Speicher (Memory) einer Anwendung scannen.
Dazu benutze ich ReadProcessMemory in einer Schleife und suche Daten mit einer festen Länge ,
Die Eingabe erfolgt als String, und ich weiß, dass der in der Anwendung Unicode-codiert vorliegt.
Und ich muss prüfen ob der Wert lpBuffer: Pointer von ReadProcessMemory der vom Nutzer eingegebene String ist.
Es ist z.B.
X('erwen') = 7471205
X('testx') = 6619252
Und damit kann ich ja die Adressen herauskriegen wo der String gespeichert ist. Dazu muss ich aber wissen ob lpbuffer den ich als Integer habe, gleich dem String ist.
m.fuchs hat geschrieben:Du kannst nur Typen casten, die auch ineinander umwandelbar sind. Char zu Integer würde zum Beispiel gehen. Aber AFIAK keinen String in einen Integer.
Ich bin mir sicher, ich hab das unter einer anderen FPC mit integer(str) geschafft.

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: Type Casting String to Integer mit Unicode

Beitrag von theo »

Klingt ziemlich wirr für mich. Unicode ist erstmal keine Kodierung. UTF-8 oder UTF-16 sind Kodierungen.
Ein String ist kein Integer. Ich wüsste nicht wie. Allenfalls kann man einen Buchstaben als Integer darstellen.
Oder du meinst den Zeiger auf die Speicherstelle des Strings, resp. des ersten Char des Strings, Den kann man als Zahl sehen, aber nicht als Integer.

Kann sein, dass ich dich nicht verstehe. Dann erklär's bitte nochmal.

e445697
Beiträge: 11
Registriert: Fr 22. Jun 2012, 11:46

Re: Type Casting String to Integer mit Unicode

Beitrag von e445697 »

Vielleicht verstehe ich es auch nicht richtig.
Was mein Ziel ist, habe ich ja erklärt - hoffentlich kann man das verstehen.

Nur wie kann ich das umsetzen, ich lese mit ReadProcessMemory nur irgendeinen Wert aus. Was dieser aber repräsentiert, muss ich noch angeben. Es ist nämlich ein UnicodeString. Das, was ich mit ReadProcessMemory auslese habe ich bisher nur als Zahl (und die wiederum als Integer zu einem String ausgegeben)

Code: Alles auswählen

 
rdata:Integer
--
Inc(address);
ReadProcessMemory(proc, Pointer(address), @rdata, 10, nil)
So klappt das auch.

Ich hab auch schon versucht
rdata:String oder als andere zu deklarieren, aber dann gibts nen SIGSEGV-Fehler.

Wie kann ich das dann machen?

Edit1: In C/C++ kann man auch Casten was man will
Edit2: Habe auch mal versucht {$mode Delphi}{$H+} weil ich ein paar Forenbeiträge von Delphiforen dazu gesehen habe - aber bringt gar keinen Unterschied.
Edit3: ICh bin jetzt weiter gekommen: Ich habe mal ab einer Startadresse vom "proc" wo ich weiß, dass da ein UnicodeString beginnt mal von dort aus die 10 folgenden Adressen mit ReadProcessMemory ausgelesen. Ich erhalte den String bspweise "Text" als Ascii(T) , 0 , Ascii(e) , 0 , ascii(x) , 0, ascii (t) , 0
Damit kann ich mein Anliegen auch lösen, allerdings weiß ich noch noch nicht, wie dann z.B. ReadProcessMemory mit nSize=5 die einzelnen Einträge zusammenrechnet - würde mich interessieren

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2805
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Type Casting String to Integer mit Unicode

Beitrag von m.fuchs »

Hallo e445697 oder markkowalt?
e445697 hat geschrieben:Ich hab auch schon versucht
rdata:String oder als andere zu deklarieren, aber dann gibts nen SIGSEGV-Fehler.
Da behaupte ich mal, das liegt daran dass der String nicht vorher mit SetLength auf die gewünschte Länge gebracht wurde. Oder alternativ deklariest du rdata als String[10], dann passen auch zehn Zeichen rein.
e445697 hat geschrieben:Edit1: In C/C++ kann man auch Casten was man will
Dann nimm doch C. :wink: In Pascal geht manches aus gutem Grund nicht.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: Type Casting String to Integer mit Unicode

Beitrag von theo »

Ich würde da mal einen PChar übergeben.

e445697
Beiträge: 11
Registriert: Fr 22. Jun 2012, 11:46

Re: Type Casting String to Integer mit Unicode

Beitrag von e445697 »

theo hat geschrieben:Ich würde da mal einen PChar übergeben.
ok, nur leider funktioniert Setlength da nicht

Mit Freememory(str,size) habe ich es mal probiert, da kommt Access Violation?!
GetMem(str,size) gibt SIGSEGV!

und es ist
str:PChar;
size:Integer=10;

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: Type Casting String to Integer mit Unicode

Beitrag von theo »

Verstehe wieder nicht ganz, was du gemacht hast.
Dann lies halt Char für Char aus (oder meinetwegen WideChar), du kannst ja die Länge in nSize angeben.

Warum willst du eigentlich so ein komisches Zeug machen?

e445697
Beiträge: 11
Registriert: Fr 22. Jun 2012, 11:46

Re: Type Casting String to Integer mit Unicode

Beitrag von e445697 »

Danke! Ja, das geht jetzt. Ich habe den Buffer dann als Byte angegeben, nSize gleich 1, und mittels Chr(b) konvertiert, man hätte sicherlich auch gleich b als Char deklarieren können.

Jetzt interessiert mich noch, wie ich einen Bereich scannen kann, wenn ich eine Schleife habe die dann die Adressen von $00000000 bis $FFFFFFFF also den gesamten Bereich durchläuft, würde es ja ewig dauern. Wie kann ich das also beschleunigen? Oder gibt es vielleicht eine andere Methode?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6763
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Type Casting String to Integer mit Unicode

Beitrag von af0815 »

Einlesen eines großen Blocks, innerhalb dieses Blocks nur auf ein Zeichen vergleichen und nur dort wo das eine Zeichen verwendet wird, die restlichen Zeichen kontrollieren. Eventuell bekommst du ja auch noch heraus, wieviel und wo die Speicherbereiche des anderen Prozesses liegen. Dann wird's auch weniger zum Suchen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

e445697
Beiträge: 11
Registriert: Fr 22. Jun 2012, 11:46

Re: Type Casting String to Integer mit Unicode

Beitrag von e445697 »

Ok, das probier ich gleich.
Übrigens meine ich das mit Casten:
Ich hab mir mal im Hexeditor angeschaut wie diese sogenannten Unicode-Strings da vorzufinden sind. Und da sind sie, wie ich das hier in meinem dritten Edit versucht habe zu erklären.

Nun habe ich mir das Zahlensystem zur Basis 256 einfach gedacht, und dann geraten ob man von vorne oder hinten durchzählt, also die Richtung (ich meine das ist dann MSB bzw LSB) und folgendes herausgefunden:
Der String "er" ist ja als Byte "101,0,114,0" und dann mit dem Zahlensystem als Grundlage ist = 101*256^0 + 0*256^1 + 114*256^2 + 0*256^3
Dann habe ich diese Funktion geschrieben:

Code: Alles auswählen

function CastUnicodeStringToInteger(str: string): integer;
var
  i, r: integer;
begin
  r := 0;
  for i := 0 to Length(str) - 1 do
    r := r + Ord(str[i + 1]) * (256 ** (2 * i));
  Result := r;
end;
Und das klappt wie ich mir das vorstelle :D , vielleicht habe ich mich einfach nicht klar genug ausgedrückt

Probieren nun einen größeren Block auszulesen,
Dann könnte ich da ja modulo 256 rechnen um den LSB zu kriegen, also, wie ich ja herausgefunden habe, den ersten Buchstaben..
Edit: Das brauche ich doch garnicht ?! Ich kann doch auch den einfach als Byte deklarieren und dann macht der das automatisch, und zusätzlich spar ich mir Speicher.

Ich probiere es sofort aus!

Edit. ok, funktioniert, ist aber viel zu langsam. Wie will ich denn in einem großen Block auf ein einzelnes Zeichen prüfen? Ich habe jetzt nSize=1, und vergleiche es mit dem ersten Zeichen und wenn das richtig ist prüfe ich die restlichen mit Beachtung, dass dazwischen das Zeichen immer #0 ist (Unicode).
Da muss ich ja trotzdem alle Adressen durchlaufen lassen.

Antworten