Die Items der Liste sind pointer. Die Add-Anweisung zeigt, dass zu Zeiger auf TMyRec speicherst. Deklariere einen Typ für diese Zeiger:
Code: Alles auswählen
type
TMyRec = record
Zahl: Integer;
Name: String;
end;
PMyRec = ^TMyRec;
In der Find-Routine versuchst du den Item zu finden, bei dem das Feld Name dem übergebenen Parameter entspricht. Daher musst du die Listen-Elemente nach PMyRec casten, denn diese sind in der Liste gespeichert. Dein Cast nach TMyList geht auf jeden Fall schief!
Zweiter Fehler: Du hast in der Listen-Definition ein ominöses Feld fRec. Wozu? Ich denke eher, du weißt nicht, wie man auf die Listenelemente zugreift und versuchst dich daran irgendwie vorbeizumogeln. Richtig ist das:
Code: Alles auswählen
function TmyList.Find(Item: String; var wc: TMyRec): Boolean;
var Index: Integer;
begin
Result := false; Index := 0;
while Index < self.Count do // self.Count-1 ist falsch, weil der letzte Listeneintrag nicht geprüft wird!
begin
// if TMyList(Items[Index]).fRec.Name = Item then
if PMyRec(Items[Index])^.Name = Item then
begin
wc := PMyRec(Items[Index])^;
// wc := fRec;
Result := true;
Index := self.Count;
end;
inc(Index);
end;
end;
Damit sollte dein Programm nicht mehr abstürzen. Es läuft aber immer noch nicht richtig, weil das Element "Bettina" nicht gefunden wird, obwohl du es ja hinzugefügt hast.
Du machst dir beim Befüllen der Liste das Leben zu einfach. Ein globaler Record, dessen Elementen du immer wieder andere Werte zuweist, ist immer noch dieselbe Variable, d.h. dessen Adresse @ARec ist immer dieselbe.
Richtig wäre, für jedes Listenelement eine eigene Variable anzulegen:
Code: Alles auswählen
var
ARec1, ARec2, ARec3: TMyRec;
begin
AList := TMyList.Create;
ARec1.Zahl := 1;
ARec1.Name := 'Anderas';
AList.Add(@ARec1);
ARec2.Zahl := 2;
ARec2.Name := 'Bettina';
AList.Add(@ARec2);
ARec3.Zahl := 3;
ARec3.Name := 'Claus';
AList.Add(@ARec3);
Oder noch besser: Speichere die Variablen auf dem Heap:
Code: Alles auswählen
var
ARec: PMyRec;
begin
AList := TMyList.Create;
New(ARec);
ARec^.Zahl := 1;
ARec^.Name := 'Andreas';
AList.Add(ARec);
New(ARec);
ARec^.Zahl := 2;
ARec^.Name := 'Bettina';
AList.Add(ARec);
New(ARec);
ARec^.Zahl := 3;
ARec^.Name := 'Claus';
AList.Add(ARec);
Was jetzt noch fehlt, ist am Programm-Ende die Listenelemente wieder vom Heap zu löschen. und auch die Liste zu löschen.
Alles in allem funktioniert es so:
Code: Alles auswählen
program listdemo;
uses Classes, Sysutils;
type
TMyRec = record
Zahl: Integer;
Name: String;
end;
PMyRec = ^TMyRec;
TMyList = class(TList)
private
fRec: TMyRec;
public
function Find(Item: String; var wc: TMyRec): Boolean;
end;
function TmyList.Find(Item: String; var wc: TMyRec): Boolean;
var Index: Integer;
begin
Result := false; Index := 0;
while Index < self.Count do
begin
// if TMyList(Items[Index]).fRec.Name = Item then
if PMyRec(Items[Index])^.Name = Item then
begin
wc := PMyRec(Items[Index])^;
// wc := fRec;
Result := true;
Index := self.Count; //while Schleife beenden!
end;
inc(Index);
end;
end;
var
ARec: PMyRec;
AList: TMyList;
foundRec: TMyRec;
i: Integer;
begin
AList := TMyList.Create;
try
New(ARec);
ARec^.Zahl := 1;
ARec^.Name := 'Anderas';
AList.Add(ARec);
New(ARec);
ARec^.Zahl := 2;
ARec^.Name := 'Bettina';
AList.Add(ARec);
New(ARec);
ARec^.Zahl := 3;
ARec^.Name := 'Claus';
AList.Add(ARec);
WriteLn(AList.Count, ' items');
for i:=0 to AList.Count-1 do
with PMyRec(AList[i])^ do
WriteLn('Index ', i, ': Zahl ', Zahl, ', Name: ', Name);
if AList.Find('Claus', FoundRec) then WriteLn('found') else WriteLn('not found');
finally
for i := 0 to AList.Count-1 do
Dispose(PMyRec(AList[i]));
AList.Free;
end;
ReadLn;
end.