Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Zweidimensionale Arrays jeweils um 1 verlängern?


Stoffel1984 - Fr 13.02.04 09:43
Titel: Zweidimensionale Arrays jeweils um 1 verlängern?
Hallo,

bei nem Eindimensionalen Array vergrößere ich das dynamische Array ja so:


Delphi-Quelltext
1:
Setlength(Array,Length(Array)+1);                    


Wie aber vergrößere ich

1. Die Erste Dimension

2. Die Zweite Dimension

des Arrays?!

Hab mir schon das Array Tutorial durchgelesen - allerdings hab ich das nicht drin gefunden!

Danke schonmal,

Stoffel


Christian S. - Fr 13.02.04 09:55

Hallo!

Doch, es steht im Array-Tutorial. Dort werden zweidimensionale Arrays mit einer Größe versehen. Und genauso macht man es auch, wenn man man einem Array eine neue Größe verpasst.

Stichwort: "Ein zweidimensionales Array ist ein 1-dim Array, dessen Elemente wieder Arrays sind."

MfG
Peter


Stoffel1984 - Fr 13.02.04 10:10

Hallo,

danke erstmal für die schnelle Antwort!
Deinem Beispiel zur Folge müsste es am Beispiel einer Tabelle
also so sein:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
SetLength(my_2d_int_array,3); 
// Das Array mit erstmal 3 Dimensionen erstellen (Zeilen)
SetLength(my_2d_int_array[0],1); 
// Erste Dimension (Zeile) bekommt die Länge 1 zugewiesen
SetLength(my_2d_int_array[1],5); 
// Zweite Dimension (Zeile) bekommt die Länge 5 zugewiesen
SetLength(my_2d_int_array,[2],7);
// Dritte Dimension (Zeile) bekommt die Länge 7 zugewiesen


Theoretisch kann ich das Array in der zweiten Zeile dann folgendermaßen vergrößern:


Delphi-Quelltext
1:
SetLength(my_2d_int_array[1],Length(my_2d_int_array)+1);                    


Hab ich das so richtig interpretiert?


Gruß, Stoffel


AndyB - Fr 13.02.04 10:46

Zitat:
jeweils um 1 verlängern

Das würde ich unterlassen, denn der Speichermanager dankt es dir mit einem enormen Speicherverbrauch. Aus diese weise werden aus 10KB ein Verbrauch von ca. 200MB.
Besser du ermittelst zuerst die maximale Länge des Arrays und setzt diese, anstatt jedesmal um 1 Element zu vergrößern. Und wenn das nicht möglich ist, solltest du das Array immer um einen Delta-Wert erhöhen und eine Variable "Effektive Länge" mitführen, die die Anzahl der genutzen Elemente enthält. Am Schluss setzt du dann die Arraylänge auf diese "Effektive Länge". Damit hast du nur 2 mal Speicher reserviert und nicht wie bei der +1 Methode n mal.


Stoffel1984 - Fr 13.02.04 10:57

Hallo,

das mit dem +1 war als Beispiel weil es in meiner Schleife nunmal so geschehen muss. Aber effektiv lese ich zuerst Length des Arrays aus und vergrößere wenn es sein muss um 1.

So meintest du es doch!?
Oder hab ich dich grade missverstanden?

Stoffel


Christian S. - Fr 13.02.04 16:01

Hallo!

Was AndyB völlig zu Recht meinte, ist, dass Delphi bei der Längenänderung eines Arrays das Array immer komplett kopiert. Dies dauert erstens sehr lange und verbraucht mit der Zeit auch eine Menge Speicher. Daher sollte man SetLength so wenig wie möglich nutzen.

Dein Code, um die zweite Zeile zu verlängern, ist nicht ganz korrekt. Denn Du rufst die Länge des "Haupt"arrays ab und verwendest diese für ein "Unter"array. Du solltest als Length(my_2d_int_array[1]) verwenden.

MfG
Peter


Delete - Fr 13.02.04 16:43

Peter Lustig hat folgendes geschrieben:
Was AndyB völlig zu Recht meinte, ist, dass Delphi bei der Längenänderung eines Arrays das Array immer komplett kopiert.


Echt? Ich dachte, dass macht es nur, wenn die Lücke im Speicher bis zum nächsten belegten Block zu klein wird. Außerdem, dachte ich, wird diese Lücke dann doch für die nächste passende GetMem-änliche Belegung genutzt.


Stoffel1984 - Fr 13.02.04 21:39

Peter Lustig hat folgendes geschrieben:
Was AndyB völlig zu Recht meinte, ist, dass Delphi bei der Längenänderung eines Arrays das Array immer komplett kopiert. Dies dauert erstens sehr lange und verbraucht mit der Zeit auch eine Menge Speicher. Daher sollte man SetLength so wenig wie möglich nutzen.


Danke... :oops:

Wie ist es dann möglich effektiv mit dyn. Arrays in Schleifen zu arbeiten?

Sollte doch möglich sein, oder?

Stoffel


AndyB - Fr 13.02.04 21:45

Stoffel1984 hat folgendes geschrieben:
Wie ist es dann möglich effektiv mit dyn. Arrays in Schleifen zu arbeiten?

Liest du eigentlich bei meinem Posting n nur den ersten Satz?


Zitat:
Echt? Ich dachte, dass macht es nur, wenn die Lücke im Speicher bis zum nächsten belegten Block zu klein wird.

Da der Delphi-Speichermanager auf 4 Byte ansrichtet, ist das bei vergrößern von Arrays fast überhaupt nicht möglich.

Zitat:
Außerdem, dachte ich, wird diese Lücke dann doch für die nächste passende GetMem-änliche Belegung genutzt.

Das schon, aber wenn nichts kleineres kommt, bleibt der Speicher "von Windows aus gesehen" reserviert. Und es ist in einer Schleife zum vergrößern des Arrays recht selten, dass in den alten Platz etwas hineinpasst. Zudem muss eine gesamte Speicherseite frei sein, damit der Delphi-Speichermanager wieder Speicher an Windows zurückgibt.