![]() |
Dynamische Arrays "zu Fuß"
Dynamische Arrays sind ja erst ab D4 und höher bekannt. Aber es gibt ja schon unter D3 Stringliste, was ja im Endeffekt auch nur ein dynmaisches Array of String ist. Da ich damit leibäugle mir D3 Professional ("Delphi for Kids" läßt grüßen) zu kaufen und ich des öfteren doch auf dynamische Arrays angewiesen bin, wollte ich mal fragen, wie man dynamische Arrays zu Fuß, also selber erstellt.
|
Re: Dynamische Array "zu Fuß"
Dynamische Arrays funktionieren ja so, dass bei einem Aufruf von SetLength() soviel Speicher alloziert wird, wie das Array benötigt (also Länge des Array * Elementgröße). Der Zugriff auf ein Speicherelement erfolgt mit der Formel Startadressse + Index * Elementgröße. Bei jedem Aufruf von SetLength wird nun das Array an einen anderen Speicherplatz kopiert und der alte Speicher freigegeben. Pack das ganze in eine schöne Klasse und das sollte es gewesen sein.
OK, du musst für jeden Datentyp eine eigene Implementierung machen, aber das dürfte weitgehend mit C&P zu lösen sein. So mal ein Beispiel, wie der Umgang mit diesem Objekt wäre. Die Daten selbst wären über einen Pointer abgespeichert, außerdem muss die Anzahl der Einträge gespeichert werden.
Delphi-Quellcode:
SetLength würde folgendes tun:
//die Klasse heißt TDynArray
myArray := TDynArray.Create(1); //Array mit der Länge erzeugen, im Konstruktor Aufruf von SetLength myArray[0] := myVar; //myVar an Startposition + 0 schreiben myArray.SetLength(2); //jetzt werden die ganzen Daten des Array an eine neue Speicherstelle kopiert myArray.Free; - NeueLänge * Elementgröße Bytes Speicher allozieren - AlteLänge * Elementgröße Bytes ausgehend von DataPointer in neuen Speicher kopieren - DataPointer mit alter Länge freigeben - DataPointer bekommt die Adresse des neuen Speicherbereichs - Fallunterscheidung: bei Länge 0 kein Kopieren nötig. Der Zugriff auf ein Element: - Die Adresse Index * Elementgröße + Datapointer dereferenzieren und in entsprechenden Typ casten So könnte man das lösen. |
Re: Dynamische Array "zu Fuß"
Ich habe mal versucht das irgendwie umzusetzten, nach einen Tipp von tommie-lie, der hat sich aber leider unter die Dusche verdrückt.
Bitte nicht lachen, mit Zeigern habe ich es nicht so.
Delphi-Quellcode:
Ich bekomme allerdings eine AccessViolation.
type
PString = ^String; var StringArray: PString; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin GetMem(StringArray, sizeof(StringArray)+1*sizeof(PString)); PString(StringArray)^ := Edit1.Text; end; |
Re: Dynamische Arrays "zu Fuß"
Hallo Luckie,
möchtest Du wirklich dyn. Array verwenden oder machst Du das nur aus interesse ? TList liefert eigentlich schon alles was Du brauchst. Wenn Du auf max. Geschwindigkeit aus bist dann versuche es mit einer verketteten Liste (beispiele finden sich überall). Ich bin noch nie in eine Situation gekommen die ich nur mit einem dyn. Array lösen konnte. Deshalb behaupte ich: !!! Dyn. Array braucht keiner!!! Ich glaube die dyn. Array's wurden nur für Basic-Programmierer in Delpih aufgenommen. |
Re: Dynamische Arrays "zu Fuß"
Zitat:
|
Re: Dynamische Arrays "zu Fuß"
Nun ja, interesse und weil D3 keine dynamischen Arrays kennt.
Mit TList habe ich noch nie gearbeitet. Kennt das D3 denn? Und wie ginge es damit? |
Re: Dynamische Arrays "zu Fuß"
Hallo Luckie
Zitat:
TList ist in der Delphi-Hilfe bestens dokumentiert. |
Re: Dynamische Arrays "zu Fuß"
Ich würds gar nicht so kompliziert machen und auf einen Typ ausrichte.
Hab hier mal was kleines geschrieben, so wie ichs mir vorstelle:
Delphi-Quellcode:
unit DynArray;
interface TDynArray = class private FDataPointer: Pointer; FElementSize: Integer; FDataSize: Integer; function GetValue(Index: Integer): Integer; procedure SetValue(Index: Integer; const Value: Integer); procedure CopyData(Destination: Pointer; Size: Integer); public constructor Create(InitialLength: Integer); destructor Destroy; override; property Value[Index: Integer]: Integer read GetValue write SetValue; procedure SetLength(NewLength: Integer); end; const ElementSize = sizeof(Integer); implementation { TDynArray } procedure TDynArray.CopyData(Destination: Pointer; Size: Integer); begin CopyMemory(Destination, FDataPointer, Size); end; constructor TDynArray.Create(InitialLength: Integer); begin FElementSize := ElementSize; FDataPointer := nil; FDataSize := 0; SetLength(InitialLength); end; destructor TDynArray.Destroy; begin SetLength(0); end; function TDynArray.GetValue(Index: Integer): Integer; begin if Index > Pred(FDataSize) then //irgendeine Exception oder sowas auslösen Result := Integer(Pointer(Integer(FDataPointer) + Index * FElementSize)^); end; procedure TDynArray.SetLength(NewLength: Integer); var NewData: Pointer; begin if NewLength <> 0 then FreeMem(FDataPointer, FDataSize * FElementSize); GetMem(NewData, NewLength * FElementSize); if FDataSize <> 0 then CopyData(NewData, FDataSize * FElementSize); FreeMem(FDataPointer, FDataSize * FElementSize); FDataPointer := NewData; end; procedure TDynArray.SetValue(Index: Integer; const Value: Integer); begin if Index > Pred(FDataSize) then //irgendeine Exception oder sowas auslösen Integer(Pointer(Integer(FDataPointer) + Index * FElementSize)^) := Value; end; end. |
Re: Dynamische Arrays "zu Fuß"
So, nach der Anregung von Herrn Schumann die Lösung mit TList:
Delphi-Quellcode:
Eigentlich auch so in der Hilfe zu finden.
type
StringArray = record MyString: String; end; PStringArray = ^StringArray; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var MyList: Tlist; sa: PStringArray; Loop: Integer; begin MyList := TList.Create; try New(sa); sa.MyString := 'Egon'; MyList.Add(sa); New(sa); sa.MyString := 'Klaus'; MyList.Add(sa); New(sa); sa.MyString := 'Michaela'; MyList.Add(sa); for Loop := 0 to myList.Count-1 do begin sa := MyList.Items[Loop]; Listbox1.Items.Add(sa.MyString); end; for Loop := 0 to MyList.Count-1 do begin sa := MyList.Items[Loop]; Dispose(sa); end; finally FreeAndNil(MyList); end; end; Zu beahcten ist nur, dass man vor dem Hinzufügen, neuen Speicher reserviert (New) für den Record und nach Gebrauch selbigen wieder frei gibt (Dispose). Ist eventuell etwas umständlicher, dafür ist man mit dem Zeiger auf den Record aber felxibeler, man kann mehr Speichern und muss nicht auf mehrdimensionale Arrays zurückgreifen. |
Re: Dynamische Arrays "zu Fuß"
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz