Autor Beitrag
synogen
Hält's aus hier
Beiträge: 5

WinXP Pro
D7 Prof
BeitragVerfasst: Do 25.11.04 16:08 
mein problem besteht darin, dass ich mehrere records habe die alle ungefähr so aufgebaut sind:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type
     daten = record
          d1:string[50];
          d2:string[70];
          d3:string[10],
     end;


diese records will ich nun ausgeben, aber vorher will ich überprüfen ob der record leer ist (also ob keines der string felder einen wert enthält).
diese überprüfung will ich aber in eine funktion machen, welche für alle records funktioniert (zumindest alle die nur strings enthalten), d.h. die funktion muss im stande sein unabhängig vom typ zu erkennen ob der record leer ist oder nicht.

meine gedanken dazu sind folgendermaßen:

1. ich übergebe den record an die funktion als pointer (damit es mit allen record typen klappt)
2. ich erstelle einen zweiten record vom selben typ wie der übergebene, und leere ihn mit FillChar, dann erstelle ich einen pointer auf diesen record
3. ich vergleiche die beiden record-pointer mit hilfe von CompareMem

da dies leider auch nach mehrstündigem probieren wenig erfolg brachte wollte ich fragen ob vielleicht schon mal jemand so etwas, oder so etwas ähnliches gemacht hat und weiß, wie das gehen könnte, danke im vorraus!
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Do 25.11.04 16:27 
Das liegt an dem Aufbau der Arrays und dem aussehen im speicher:

Einleeres Array, also mit '' - strings vom typ den du angegeben hast sieht im Speicher ungefähr so aus:

ausblenden Quelltext
1:
00A3040103430000007E00100149005A000100000001000000050000005254D377A3040103FCF512000000000004841400000200000400000004000000470000001500000013000000048414000F001200030000000700000070001001280861002500000004841400000200000300000003000000250000000200000077324000FC954200					


und da ist klar, dass es nicht mit mit 00 - bytes übereinstimmt....

Lösung hab ich zwar noch nicht, schaue aber mal ob mir noch was einfällt
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Do 25.11.04 16:35 
du müsstest bei der initialisierung der variablen und vor jeder zuweisung den Berich des strings mit 00-bytes fluten, dann klappts mit dem vergleich.

wenn man einem string des records einen kürzeren zuweist als der der vorher drin stand, dann setzt delphi im speicher einen zähler für diesen string runter und ändert im speicher nur die bytes die es betrifft. die im string gelöschten zeichen bleiben im speicher stehen, da delphi sie aufgrund des zählers nicht beachtet. dieser datenmüll verhindert deinen vergleich.
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Do 25.11.04 16:40 
Probiers mal mit folgender Zuweisungsfunktion


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure SetString(P:Pointer;IN_string:string;IN_Length:integer);
begin
  fillchar(P,IN_Length,#0);
  string(P):=IN_String;
end;


ausblenden Delphi-Quelltext
1:
  SetString(@myrec.d1,Edit1.Text,Length(myrec.d1));					


anstatt mit
ausblenden Delphi-Quelltext
1:
 myrec.d1:=Edit1.text;					


Dann sollte auch deine Vergleichsfunktion hinhauen.
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Do 25.11.04 16:43 
Vielleicht hilft dir ansonsten folgende Funktion:

Sie gibt dir den Speicherinhalt als Hexstring aus. Hilft vielleicht bei der analyse, wenn man weiss, was man eigentlich vergleicht. :wink:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
type
  Trec = record
    d1: string [50];
    d2: string [70];
    d3: string [10];
  end;
var
  myrec: trec;

function getbytes(IN_P:Pointer; IN_Size: integer):string;
var i: integer;
    c: Pchar;
begin
  c:=PChar(IN_P);
  Result:='';
  for i:= 0 to IN_Size-1 do
  begin
    Result:=Result+inttohex(Ord(c[i]),2);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text:=getbytes(@myrec,sizeof(myrec));
end;
synogen Threadstarter
Hält's aus hier
Beiträge: 5

WinXP Pro
D7 Prof
BeitragVerfasst: Do 25.11.04 18:15 
erstmal vielen dank für die viele und ausführliche hilfe

der vergleich der beiden records funktioniert ja, mein problem ist eigentlich nur das in eine funktion zu packen, die in etwa so aussehen würde:

typdefinition
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type
     daten = record
          d1:string[50];
          d2:string[70];
          d3:string[10];
     end;


funktion:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function RecIsEmpty (rec:daten;typesize:integer):boolean;
var
     emptyrec:daten;

begin
     //zweite Variable mit dem Typ von "rec" leeren
     FillChar (emptyrec,SizeOf (emptyrec),0);
     //die beiden Variablen per CompareMem vergleichen
     result:=CompareMem (@rec,@emptyrec,typesize);
end;


dies funktioniert (oder sollte zumindest) für den typ "daten", aber nicht für andere datentypen, ich müsste also irgendwie den typ dynamisch machen, so das es beispielsweise so aussieht

ausblenden Delphi-Quelltext
1:
2:
3:
function RecIsEmpty (var rec;typesize:integer):boolean;
var
     emptyrec:<variabler datentyp hier>;


so dass der typ der "rec" und "emptyrec" variable erst zur laufzeit dynamisch gesetzt wird, und dynamische (zur laufzeit) variablentypen lassen nur pointer und variants zu, oder irre ich mich da?

ps: das mit fillchar vor den zuweisungen mach ich bereits :)
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Fr 26.11.04 09:32 
Probiers mal so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
function RecIsEmpty (rec:Pointer;typesize:integer):boolean;
var
  emptyrec:PChar;
  i:integer;
begin
  //Vergleichsvariable anlegen und durchnullen
  emptyrec:=StrAlloc(typesize);
  for i:= 0 to typesize - 1 do
    emptyrec[i]:=#0;
  //die beiden Variablen per CompareMem vergleichen
  result:=CompareMem (rec,emptyrec,typesize);
  StrDispose(emptyrec);
end;


Aufruf:
ausblenden Delphi-Quelltext
1:
  Mybool:=recisempty(@myrec,sizeof(myrec)); //der typ von myrec ist frei wählbar					
synogen Threadstarter
Hält's aus hier
Beiträge: 5

WinXP Pro
D7 Prof
BeitragVerfasst: Fr 26.11.04 09:54 
supi :)

hat prima funktioniert, alle felder des records werden verglichen, vielen dank nochmal für die hilfe ;)
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 26.11.04 12:27 
Hm.. da ging wohl bei der Umstellung mein Beitrag gestern verloren.. naja, hier nochmal.. nachdem du ja die Typesize mitgibst isses eigentlich ganz simpel:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function RecIsEmpty (pRec: Pointer; dwTypeSize: DWord): Boolean;
var
  p: PChar;
begin
  Result := True;
  p := pRec;
  while Result and ((DWord(p) - dwTypeSize) <= DWord(pRec)) do
  begin
    Result := p^ = #0;
    Inc(p);
  end;
end;


So sparst du dir irgendeinen Speicher zu reservieren, diesen mit Nullen zu füllen und anschließend wieder freizugeben..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
synogen Threadstarter
Hält's aus hier
Beiträge: 5

WinXP Pro
D7 Prof
BeitragVerfasst: Fr 26.11.04 13:51 
leider hab ich den quellcode bei meiner praktikumsstelle, kanns also nicht ausprobieren momentan, aber ich verstehe wie du es meinst und das es praktischer ist als speicherreservierung etc.
ich werds gleich montag einbauen :)

danke vielmals