Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi 32 Bit Wert verschieden interpretieren (https://www.delphipraxis.net/168368-32-bit-wert-verschieden-interpretieren.html)

zeras 17. Mai 2012 15:54

32 Bit Wert verschieden interpretieren
 
Hallo,

ich bekomme über eine Schnittstelle 32 Bit Werte. Diese sind aber manchmal Single Zahlen, Longword und manchmal LongInt. Wenn ich diese falsch "anfasse", kommt immer wieder Fehler bei Bereichsüberschreitung. Wie macht ihr das?
Nehmt ihr mehrere verschiedene Variablen und deklariert sie dann über absolute auf die selbe Adresse oder wie macht ihr das?

Delphi-Laie 17. Mai 2012 16:13

AW: 32 Bit Wert verschieden interpretieren
 
Inwiefern werden die "falsch angefaßt"? Beispielcode?

zeras 17. Mai 2012 16:23

AW: 32 Bit Wert verschieden interpretieren
 
Ist ein wenig schwer zu erklären.
Wie gesagt, ich bekomme 4 Bytes und muss diese unterschiedlich interpretieren (single, longword, longint). Dann muss dieser Wert aber wieder an eine Funktion weitergereicht werden. Da ich aber nur diese 4 Bytes habe, weiß ich nicht, wie ich diese dann weiterreichen kann.

WriteToSvr(Adr, v) wobei hier v ein single wäre
WriteToSvr(Adr, v) wobei hier v ein longword wäre
WriteToSvr(Adr, v) wobei hier v ein longint wäre

Vielleicht irgendein Pointer, der alles beinhalten kann?

Popov 17. Mai 2012 16:25

AW: 32 Bit Wert verschieden interpretieren
 
Zum Prüfen

Delphi-Quellcode:
    { Prüft ob String ein Integerwert ist }
function IsValidInteger(S: String): Boolean;
var
  I, Code: Integer;
begin
  Val(S, I, Code);
  Result := Code = 0;
end;

    { Prüft ob String ein Currencywert ist }
function IsValidCurrency(S: String): Boolean;
var
  C: Currency;
begin
  Result := TextToFloat(PChar(S), C, fvCurrency);
end;

    { Prüft ob String ein Extendedwert ist }
function IsValidExtended(S: String): Boolean;
var
  E: Extended;
begin
  Result := TextToFloat(PChar(S), E, fvExtended);
end;
Ok, ich sehe du brauchst, LongInt, LingWord und Double. LongInt kannst du mit der oberen Funktion testen, für Single kannst du dir mit TryStrToFloat eine Funktion erstellen.

Delphi-Quellcode:
function TryStrToFloat(const S: string; out Value: Double): Boolean; overload;

//Ungeprüft

    { Prüft ob String ein Double ist }
function IsValidDouble(S: String): Boolean;
var
  Value: Double ;
begin
  Result := TryStrToFloat(S, Value);
end;

zeras 17. Mai 2012 16:41

AW: 32 Bit Wert verschieden interpretieren
 
Ich kann das vielleicht nicht so richtig rumbringen.

Als Quelle kommen 4 Bytes an. Durch Festlegung weiß ich, dass es Single, Longword oder LongInt ist. Diese können dann mittels verschiedener Spinedits verändert werden. Dazu habe ich dann an Hand der Kennung den Wert jeweils in ein Single, Longword oder LongInt gespeichert. Nun muss ich aber die verschiedenen Werte wieder über eine Funktion wieder in die 4 Bytes zurückbekommen. Vielleicht muss ich irgendwie mit overload arbeiten?

Popov 17. Mai 2012 16:47

AW: 32 Bit Wert verschieden interpretieren
 
Also nochmal, du muß es nicht prüfen, du weißt ob es Single, LongInt, LongWord ist, du willst nur wissen wie du es weiter leiten kannst?

zeras 17. Mai 2012 16:48

AW: 32 Bit Wert verschieden interpretieren
 
Zitat:

Zitat von Popov (Beitrag 1166966)
Also nochmal, du muß es nicht prüfen, du weißt ob es Single, LongInt, LongWord ist, du willst nur wissen wie du es weiter leiten kannst?

Ja, ich habe dann wieder eine Funktion, die die Daten wieder wegschreibt und dort werden einfach 4 Bytes gesendet.

Delphi-Laie 17. Mai 2012 16:53

AW: 32 Bit Wert verschieden interpretieren
 
Zitat:

Zitat von zeras (Beitrag 1166962)
Ich kann das vielleicht nicht so richtig rumbringen.

Weil m.E. Quellcode fehlt.

Zitat:

Zitat von zeras (Beitrag 1166962)
Als Quelle kommen 4 Bytes an. Durch Festlegung weiß ich, dass es Single, Longword oder LongInt ist. Diese können dann mittels verschiedener Spinedits verändert werden. Dazu habe ich dann an Hand der Kennung den Wert jeweils in ein Single, Longword oder LongInt gespeichert. Nun muss ich aber die verschiedenen Werte wieder über eine Funktion wieder in die 4 Bytes zurückbekommen. Vielleicht muss ich irgendwie mit overload arbeiten?

Ein wenig Quellcode sagt manchmal mehr als tausend Wörter.

Popov 17. Mai 2012 16:54

AW: 32 Bit Wert verschieden interpretieren
 
Hilft dir das weiter?

Delphi-Quellcode:
procedure MyTest(Value: Double); overload;
begin
  ShowMessage(FloatToStr(Value));
end;

procedure MyTest(Value: LongInt); overload;
begin
  ShowMessage(IntToStr(Value));
end;

procedure MyTest(Value: LongWord); overload;
begin
  ShowMessage(IntToStr(Value));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  d: Double;
  i: LongInt;
  w: LongWord;
begin
  d := 1.7e308;
  i := -2147483647;
  w := 4294967295;

  MyTest(d);
  MyTest(i);
  MyTest(w);
end;
Und wie gesagt, ob du d oder i oder w als Variable nimmst, mußt du selbst vorher prüfen.

zeras 17. Mai 2012 16:57

AW: 32 Bit Wert verschieden interpretieren
 
Zitat:

Zitat von Popov (Beitrag 1166973)
Hilft dir das weiter?

Delphi-Quellcode:
procedure MyTest(Value: Double); overload;
begin
  ShowMessage(FloatToStr(Value));
end;

procedure MyTest(Value: LongInt); overload;
begin
  ShowMessage(IntToStr(Value));
end;

procedure MyTest(Value: LongWord); overload;
begin
  ShowMessage(IntToStr(Value));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  d: Double;
  i: LongInt;
  w: LongWord;
begin
  d := 1.7e308;
  i := -2147483647;
  w := 4294967295;

  MyTest(d);
  MyTest(i);
  MyTest(w);
end;
Und wie gesagt, ob du d oder i oder w als Variable nimmst, mußt du selbst vorher prüfen.

So werde ich wohl erst mal ins Rennen gehen. Das sollte in etwa dem entsprechen, was ich brauche.
Vielen Dank.

zeras 17. Mai 2012 17:20

AW: 32 Bit Wert verschieden interpretieren
 
Ich habs nun mal so gemacht. Muss nur noch testen. Das Array ar4 enthält dann die 4 Bytes, unabhängig, ob es Single, LongWord oder LongInt ist.

Delphi-Quellcode:
Function WriteToSvr(Address: Longword; dValue: Longword): Boolean; overload;
var
  Adr1   : Longword;
  Wert  : Longword;
  ar: ar4 absolute Wert;

begin
  Result := False;
  Adr1 := Address;
  Wert := dValue;

  If WriteToSvr3(Adr1, ar) then begin
    Result := True;
  end;
end;

Function WriteToSvr(Address: Longword; dValue: LongInt): Boolean; overload;
var
  Adr1   : Longword;
  Wert  : LongInt;
  ar: ar4 absolute Wert;

begin

  Result := False;
  Adr1 := Address;
  Wert := dValue;

  If WriteToSvr3(Adr1, ar) then begin
    Result := True;
  end;
end;


Function WriteToSvr(Address: Longword; dValue: Single): Boolean; overload;
var
  Adr1   : Longword;
  Wert  : Single;
  ar: ar4 absolute Wert;

begin
  Result := False;
  Adr1 := Address;
  Wert := dValue;

  If WriteToSvr3(Adr1, ar) then begin
    Result := True;
  end;
end;

DeddyH 17. Mai 2012 17:33

AW: 32 Bit Wert verschieden interpretieren
 
Mit einem varianten Record sollte das aber auch funktionieren, und zwar kürzer.
Delphi-Quellcode:
type
  TConvRec = record
    case integer of
      0: (d: double);
      1: (i: LongInt);
      2: (w: LongWord);
      3: (LoLo, HiLo, LoHi, HiHi: Byte);
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Rec: TConvRec;
begin
  Rec.i := -2147483647;
  ShowMessage(Format('%d, %d, %d, %d', [Rec.HiHi, Rec.LoHi, Rec.HiLo, Rec.LoLo]));
  Rec.w := 4294967295;
  ShowMessage(Format('%d, %d, %d, %d', [Rec.HiHi, Rec.LoHi, Rec.HiLo, Rec.LoLo]));
  Rec.d := 1.7e308;
  ShowMessage(Format('%d, %d, %d, %d', [Rec.HiHi, Rec.LoHi, Rec.HiLo, Rec.LoLo]));
end;

jaenicke 17. Mai 2012 17:34

AW: 32 Bit Wert verschieden interpretieren
 
Für mich hört sich das sehr danach an als ob du z.B. einen varianten Record suchst... ungetestetes Beispiel, das sollte mit Delphi 2009 schon gehen:
Delphi-Quellcode:
type
  TMy4ByteData = packed record
    type
      TDataType = (dtSingle, dtInteger, dtLongWord);
    class operator implicit(const Value: TMy4ByteData): TArray<Byte>;
    case DataType: TDataType of
      dtSingle:
        (ValueAsSingle: Single);
      dtInteger:
        (ValueAsInteger: Integer);
      dtLongWord:
        (ValueAsLongWord: LongWord);
  end;

// ...

class operator TMy4ByteData.implicit(const Value: TMy4ByteData): TArray<Byte>;
begin
  SetLength(Result, 4);
  CopyMemory(Pointer(Result), @Value.ValueAsInteger, 4);
end;

procedure Example(const AValue: TMy4ByteData);
begin
  case AValue.DataType of
    dtSingle:
      ShowMessage('Single: ' + FloatToStr(AValue.ValueAsSingle));
    dtInteger:
      ShowMessage('Integer: ' + IntToStr(AValue.ValueAsInteger));
    dtLongWord:
      ShowMessage('LongWord: ' + IntToStr(AValue.ValueAsLongWord));
  end;
end;

var
  Value: TMy4ByteData;
  ValueData: TArray<Byte>;
  CurrentByte: Byte;
begin
  Value.DataType := dtSingle;
  Value.ValueAsSingle := 4.5;
  Example(Value);
  ValueData := Value;
  for CurrentByte in ValueData do
    ShowMessage(IntToStr(CurrentByte));
end;
Ich sehe schon die rote Box, aber ich poste wegen dem Operator mal trotzdem...

Popov 17. Mai 2012 18:03

AW: 32 Bit Wert verschieden interpretieren
 
Wieso das
Delphi-Quellcode:
  If WriteToSvr3(Adr1, ar) then begin
    Result := True;
  end;
nicht so?

Delphi-Quellcode:
  Result := WriteToSvr3(Adr1, ar);

zeras 17. Mai 2012 18:12

AW: 32 Bit Wert verschieden interpretieren
 
Zitat:

Zitat von Popov (Beitrag 1166986)
Wieso das
Delphi-Quellcode:
  If WriteToSvr3(Adr1, ar) then begin
    Result := True;
  end;
nicht so?

Delphi-Quellcode:
  Result := WriteToSvr3(Adr1, ar);

Gute Idee.
Ich hatte in dem Zweig ursprünglich noch etwas anderes drin. Aber jetzt nicht mehr. So könnte ich den Code noch ein wenig schlanker machen.

Popov 17. Mai 2012 18:14

AW: 32 Bit Wert verschieden interpretieren
 
Dann kannst du auch
Delphi-Quellcode:
Result := False;
entfernen.

zeras 17. Mai 2012 18:18

AW: 32 Bit Wert verschieden interpretieren
 
Zitat:

Zitat von DeddyH (Beitrag 1166981)
Mit einem varianten Record sollte das aber auch funktionieren, und zwar kürzer.

Danke für die Info.
Das mit den varianten Records muss ich mir mal später genauer anschauen.
Vielleicht kann das später in mein Projekt mit reinwachsen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz