Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - n-dimensionales dynamisches Array


_Blackhawk_ - Mo 22.01.07 21:21
Titel: n-dimensionales dynamisches Array
Der Titel sagt ja schon alles.

Wie ist es unter Delphi (genau Delphi 7) möglich ein n-dimensionales dynamisches Array zu erzeugen. Wenn möglich ohne die Verwendung von Variants, denn die scheinen mir immernoch etwas schwer verständlich. Ich habe schon daran gedacht einen Typen zu nehmen der einen dynamischen Array beinhaltet und auf sich selber verweist, aber dann würde er sich doch zu viel verweisen und der Compiler sagt mir Datengröße über 2GB.

So im Sinne von:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type TDynArray = record
DynArray:array of TDynArray;
Data: (Typ noch unklar);
end;

var DynArray:TDynArray;

(wenn das überhaupt geht ? - Compiler scheint es anzunehmen)

Hab schon hier im Forum gesucht, aber nix Nützliches dazu gefunden.

Danke schonmal für die Hilfe.

mfg _Blackhawk_

Moderiert von user profile iconChristian S.: Beitragsformatierung überarbeitet


Dragonclaw - Mo 22.01.07 22:00

Hallo,

also ein 2 dimenisonales dynamisches Array geht mit


Delphi-Quelltext
1:
2:
3:
4:
var
 Test: array of array of Integer;
begin
SetLength(Test,2,2);


Ob du einfach immer ein array of dran hängen kannst weiß ich nicht


_Blackhawk_ - Mo 22.01.07 22:08

Das mit dem array of dranhängen ist kein Problem.
Der Punkt ist das ich nicht weis wie n-dimensional
das Array ist. Das kommt dann erst zur Laufzeit.


Delete - Mo 22.01.07 23:09

lurk dir doch mal pointer an...

deine def. würd in etwa so aussehen...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
type pDyArray = ^tDynArray;
     TDynArray = record
      DynArray: array of pDynArray;
      Data: (Typ noch unklar);
     end;

var da: TDynArray;


weiters stichwort wäre heap. hier hilft dir die forumssuche sicher weiter.
<HTH>


_Blackhawk_ - Di 23.01.07 13:06

danke schonmal. werde mich mal ranhängen.


alzaimar - Di 23.01.07 13:13

Ich kann mir keinen Fall vorstellen, bei dem ein dynamisches mehrdimensionales Array, bei dem die Dimensionen zur Entwurfszeit nicht feststehen, die richtige Datenstruktur ist, um ein Problem zu lösen.

Kannst Du mir ein Beispiel nennen, oder dein Problem beschreiben?


_Blackhawk_ - Di 23.01.07 13:20

OK ich mach das mal an nem Beispiel fest: am besten Laufwerksstrukturen, also (Unter-)Ordner.
Jede Dimension ist ein Ordner (oder andersrum) und der Inhalt dieser wird in Data (siehe oben) geschrieben. So könnte ich mit

Delphi-Quelltext
1:
DynArray[x][y][z][...].Data                    

auf die Daten eines Unterordners zugreifen. So nach dem "Node-Prinzip".
Sozusagen eine Baumstruktur mit beliebig vielen Ästen.


alzaimar - Di 23.01.07 14:11

... Beitrag wurde der Übersicht halber gelöscht, da alles im nächsten Beitrag enthalten ist ...


alzaimar - Di 23.01.07 14:13

user profile icon_Blackhawk_ hat folgendes geschrieben:
Sozusagen eine Baumstruktur mit beliebig vielen Ästen.

Und wieso nimmst du dann keinen Baum? :gruebel:

Schau Dir doch das Interface einer TTreeView an und kopiere das einfach: Die besteht nämlich aus einer Liste von Knoten. Jeder Knoten enthält eine Liste von Kindknoten.

user profile icon_Blackhawk_ hat folgendes geschrieben:
... So könnte ich mit

Delphi-Quelltext
1:
DynArray[x][y][z][...].Data                    

auf die Daten eines Unterordners zugreifen.

Garantiert nicht, denn Du kennst die Anzahl der Dimensionen ja zur Entwurfszeit (wenn Du das o.g. eintippst) nicht.

[edit] Dieses Post sollte ein ERSATZ für das vorherige sein, ...ich lösche also mein vorheriges Post... [/edit]


Robinator - Di 23.01.07 15:05

http://www.lischke-online.de/VirtualTreeview/

Oder einfach mal hier gucken - geniale komponente.

gruss


_Blackhawk_ - Di 23.01.07 16:56

@alzaimar: ist mir garnicht aufgefallen dass das so ja nicht geht. Danke.

Ich werde mir mal die (Virtual-)TreeView-Komponente zu Gemüte führen. Wird wohl ne Weile dauern. Ich meld mich dann wieder.

Danke schonmal für die tolle Unterstützung.


_Blackhawk_ - Mi 24.01.07 10:32

So hab das TreeView mal angeguckt:
Das mit den Nodes, Childs und Siblings ist sehr umständlich finde ich.
Darum ist meine erste Idee ja garnicht so abwegig, auch wenn sie nicht funktioniert.
Habt ihr vlt noch ne Idee wie man das anders umsetzen kann ?
(Wenn nicht dann ists auch nicht so schlimm)


jaenicke - Mi 24.01.07 10:40

Naja, so umständlich mit Nodes und Siblings und so brauchst du es doch nicht...

Du erstellst eine Klasse, die einen Knoten darstellt, und darin packst du dann wieder eine Liste von Kindknoten. Wenn du willst, dann erstellst du dazu noch eine Array-Eigenschaft, die dir die einzelnen Kinder wie in einem Array zurückgibt.

Aber das ist wirklich nicht so schwierig, wie es jetzt vielleicht aussieht ;-).


_Blackhawk_ - Mi 24.01.07 12:42

hmm ... OK
Könntest du (oder andere) mir mal ein Quellcode-Beispiel geben ?
Denn deiner Erklärung kann ich jetzt auch nicht ganz folgen.


jaenicke - Mi 24.01.07 12:52

Ok, mache ich mal...
Dauert ein paar Minuten...


jaenicke - Mi 24.01.07 13:39

Soooo, hier das Beispiel:

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:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
type
  TMyNode = class(TObject)
  private
    fTestText: String;
    fChilds: TList;
    function GetChildCount: Integer;
    function GetChild(uIndex: Integer): TMyNode;
  public
    constructor Create(uTestText: String);
    destructor Destroy; override;
    procedure AddChild(uChild: TMyNode);
    procedure DeleteChild(uChild: Integer);
    property ChildCount: Integer read GetChildCount;
    property Childs[uIndex: Integer]: TMyNode read GetChild;
    property TestText: String read fTestText write fTestText;
  end;

  TForm55 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form55: TForm55;

implementation

{$R *.dfm}

{ TMyNode }

constructor TMyNode.Create(uTestText: String);
begin
  fTestText := uTestText;
  fChilds := TList.Create;
end;

destructor TMyNode.Destroy;
var
  i: Integer;
begin
  for i := 0 to ChildCount - 1 do
    Childs[i].Free;
  FreeAndNil(fChilds);
  inherited;
end;

function TMyNode.GetChildCount: Integer;
begin
  Result := fChilds.Count;
end;

function TMyNode.GetChild(uIndex: Integer): TMyNode;
begin
  if (uIndex >= 0and (uIndex < fChilds.Count) then
    Result := fChilds[uIndex]
  else
    Result := nil;
end;

procedure TMyNode.AddChild(uChild: TMyNode);
begin
  fChilds.Add(uChild);
end;

procedure TMyNode.DeleteChild(uChild: Integer);
begin
  fChilds.Delete(uChild);
end;

procedure TForm55.Button1Click(Sender: TObject);
var
  i: Integer;
  Root, NewChild, NewChild2: TMyNode;
  j: Integer;
begin
  Root := TMyNode.Create('Root');
  for i := 0 to 10 do
  begin
    NewChild := TMyNode.Create('Test' + IntToStr(i));
    Root.AddChild(NewChild);
    for j := 0 to 2 do
    begin
      NewChild2 := TMyNode.Create('Test' + IntToStr(i) + ', ' + IntToStr(j));
      NewChild.AddChild(NewChild2);
    end;
  end;
  for i := 0 to Root.ChildCount - 1 do
  begin
    ShowMessage(Root.Childs[i].TestText);
    for j := 0 to Root.Childs[i].ChildCount - 1 do
      ShowMessage(Root.Childs[i].Childs[j].TestText);
  end;
  Root.Free;
end;


_Blackhawk_ - Mi 24.01.07 16:24

Wow ! Danke jaenicke !
Dein Beispiel ist wirklich super und leicht verständlich.
Das ist ein super Beispiel um die "Technik" zu verstehen.

Das Thema wäre damit fertig.


_Blackhawk_ - Do 25.01.07 15:02

ich hab daraus jetzt mal ne Unit gemacht die frei zur Verfügung steht:


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:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
unit NodeUnit;

interface

uses SysUtils, Classes;

const
  MinChildsDim=1;
  MaxChildsDim=100;

type

  TMyNode = class(TObject)
  private
    fText: String;
    ChildsList: TList;
    function GetChildCount: Integer;
    function GetChild(Index: Integer): TMyNode;
  public  
    constructor Create(Text: String);
    destructor Destroy; override;
    procedure LinkChild(Child: TMyNode);
    procedure DeleteChild(Child: Integer);
    property ChildCount: Integer read GetChildCount;
    property Childs[Index: Integer]: TMyNode read GetChild;
    property Text: String read fText write fText;
  end;

  TMyNodes = record
    Root:TMyNode;
    Childs:array[MinChildsDim..MaxChildsDim] of TMyNode;
  end;

implementation

constructor TMyNode.Create(Text: String);  
begin  
  fText := Text;  
  ChildsList := TList.Create;  
end;
 
destructor TMyNode.Destroy;  
var i: Integer;
begin  
  for i := 0 to ChildCount - 1 do  
    Childs[i].Free;  
  FreeAndNil(ChildsList);
  inherited;
end;
 
function TMyNode.GetChildCount: Integer;  
begin  
  Result := ChildsList.Count;
end;
 
function TMyNode.GetChild(Index: Integer): TMyNode;
begin  
  if (Index >= 0and (Index < ChildsList.Count) then
    Result := ChildsList[Index]
  else  
    Result := nil;  
end;
 
procedure TMyNode.LinkChild(Child: TMyNode);
begin  
  ChildsList.Add(Child);
end;
 
procedure TMyNode.DeleteChild(Child: Integer);  
begin  
  ChildsList.Delete(Child);
end;

end.