Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
fliegermichl
Lazarusforum e. V.
Beiträge: 1436 Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell
Beitrag
von fliegermichl » Mi 13. Jan 2021, 10:33
Hallo,
wenn ich eine UINT64 Zahl als String repräsentieren möchte, mache ich das so:
Code: Alles auswählen
type
// RBigIntRec definiert einen Record, welcher den Zugriff auf alle Bestandteile eines 64 Bit Integers erlaubt
RBigIntRec = record
case Integer of
1 : (BigInt : Int64); // 1 * 64 Bit
2 : (LowPart : Integer; // 2 * 32 Bit
HighPart : Integer);
3 : (LPLW : word; // 4 * 16 Bit
LPHW : word;
HPLW : word;
HPHW : word);
4 : (LPLWLSB : Byte; // 8 * 8 Bit
LPLWMSB : Byte;
LPHWLSB : Byte;
LPHWMSB : Byte;
HPLWLSB : Byte;
HPLWMSB : Byte;
HPHWLSB : Byte;
HPHWMSB : Byte);
end;
function StringToBigInt(s : string) : UInt64;
function BigIntToString(i : UInt64) : string;
implementation
function StringToBigInt(s: string): UInt64;
begin
with RBigIntRec(Result) do
sscanf(s, '%d.%d.%d.%d', [@hphw, @hplw, @lphw, @lplw]);
end;
function BigIntToString(i: UInt64): string;
begin
with RBigIntRec(i) do
Result := Format('%d.%d.%d.%d', [hphw, hplw, lphw, lplw]);
end;
BigIntToString funktioniert erwartungsgemäß.
StringToBigInt liefert nur Unfug.
Was mache ich da falsch?
Zuletzt geändert von
fliegermichl am Mi 13. Jan 2021, 13:55, insgesamt 1-mal geändert.
m.fuchs
Lazarusforum e. V.
Beiträge: 2641 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:
Beitrag
von m.fuchs » Mi 13. Jan 2021, 11:40
Vergiss
SScanf , da wild mit Pointern rumzuschießen führt nur zu Problemen.
Code: Alles auswählen
function StringToBigInt(s: string): UInt64;
var
Parts: TStringArray;
r: RBigIntRec;
begin
Parts := s.Split(['.']);
r.HPHW := StrToInt(Parts[0]);
r.HPLW := StrToInt(Parts[1]);
r.LPHW := StrToInt(Parts[2]);
r.LPLW := StrToInt(Parts[3]);
Result := r.BigInt;
end;
Geht sicher auch noch anders / besser / sicherer /schneller.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
Winni
Beiträge: 1577 Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark
Beitrag
von Winni » Mi 13. Jan 2021, 11:41
Hi!
Wenn ich mich recht entsinne solltest Du die Punkte zwischen den Parametern weglassen, also
Winni
fliegermichl
Lazarusforum e. V.
Beiträge: 1436 Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell
Beitrag
von fliegermichl » Mi 13. Jan 2021, 13:47
m.fuchs hat geschrieben: ↑ Mi 13. Jan 2021, 11:40
Vergiss
SScanf , da wild mit Pointern rumzuschießen führt nur zu Problemen.
Code: Alles auswählen
function StringToBigInt(s: string): UInt64;
var
Parts: TStringArray;
r: RBigIntRec;
begin
Parts := s.Split(['.']);
r.HPHW := StrToInt(Parts[0]);
r.HPLW := StrToInt(Parts[1]);
r.LPHW := StrToInt(Parts[2]);
r.LPLW := StrToInt(Parts[3]);
Result := r.BigInt;
end;
Geht sicher auch noch anders / besser / sicherer /schneller.
Danke das mit dem s.split kannte ich noch gar nicht.
Funktioniert!
fliegermichl
Lazarusforum e. V.
Beiträge: 1436 Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell
Beitrag
von fliegermichl » Mi 13. Jan 2021, 13:47
Winni hat geschrieben: ↑ Mi 13. Jan 2021, 11:41
Hi!
Wenn ich mich recht entsinne solltest Du die Punkte zwischen den Parametern weglassen, also
Winni
Danke für die Info aber funktioniert leider auch nicht.
Warf
Beiträge: 1912 Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64
Beitrag
von Warf » Mi 13. Jan 2021, 18:36
Das liegt daran das %d einen c "int" typen matcht. Auf den meisten modernen maschinen ein 32 bit wert. Du gibst ihm aber pointer auf words, 16 bit werte. Die 32 bit passen da nicht rein, also wird einfach was dahinter liegt überschrieben. Da sind wahrscheinlich deine anderen variablen, weshalb nur schrott bei rauskommt.
Was du brauchst für words zu lesen ist %hu für "unsigned short int". Aber selbst das muss nicht garantieren das es funktioniert, der C standard sagt das short mindestens 16 bit lang sein muss. Es wäre aber vollkommen valide wenn ein system einen 32 oder 64 bit shorttypen anbietet.
Langer rede kurzer sinn, C ist nervig und du solltest wenn möglich C funktionen vermeiden. Scanf (und auch printf) ist aber in einer eigenen Liga von Schrottigkeit und sollte man wenn möglich nicht mal mit ner Kneifzange anfassen.
Mach das lieber mit split ist einfacher, besser und wahrscheinlich sogar effizienter
Aidex
Beiträge: 60 Registriert: Do 24. Sep 2020, 07:02
OS, Lazarus, FPC: Win10 64bit, Laz v2.0.10
CPU-Target: AMD64
Beitrag
von Aidex » Mi 13. Jan 2021, 19:17
Es entspricht zwar nicht der Fragestellung, aber wäre es nicht generell besser, eine 64-Bit-Zahl als hexadezimalen String zu repräsentieren?
s:=IntToHex(Int64(x));
x:=UInt64(StrToInt64('$'+s));
fliegermichl
Lazarusforum e. V.
Beiträge: 1436 Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell
Beitrag
von fliegermichl » Do 14. Jan 2021, 10:35
Aidex hat geschrieben: ↑ Mi 13. Jan 2021, 19:17
Es entspricht zwar nicht der Fragestellung, aber wäre es nicht generell besser, eine 64-Bit-Zahl als hexadezimalen String zu repräsentieren?
s:=IntToHex(Int64(x));
x:=UInt64(StrToInt64('$'+s));
Es geht hier um eine Versionsnummer die als 64 Bit unsigned Int gespeichert wird. 8.1.10.4 z.B.
Das sähe komisch aus als Hexwert.
Wie gesagt, Die Lösung von M.Fuchs funktioniert einwandfrei.