Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi dynamische Array kopieren (letztes Element fehlt) (https://www.delphipraxis.net/148728-dynamische-array-kopieren-letztes-element-fehlt.html)

brainless 7. Mär 2010 10:39


dynamische Array kopieren (letztes Element fehlt)
 
hallo,

ich arbeite seit kurzem mit dynamischen Arrays (vorher immer mit statischen) - also bin Anfänger ;) - und nun wollte ich ein komplettes Array in ein anderes kopieren. Mein erster Ansatz mit:
Delphi-Quellcode:
procedure TForm_liste.BtnSortClick(Sender: TObject);
var i, j: Integer;
// ...
    dynArray1: array of TIrgendwas;
    dynArray2: array of TIrgendwas;
begin

  SetLength(dynArray1, 200); //Länge des dynArray's
  SetLength(dynArray2, 200); //Länge des dynArray's

// irgendwelche Werte werden dynArray1 zugewiesen ...

    FOR i := 1 TO high(dynArray1) DO
     begin
      dynArray2[i] := dynArray1[i];
     end;
hat nicht funktioniert..
habe dann gegooglet und die Funktion Copy(dynArray) gefunden:
Delphi-Quellcode:
    // Array kopieren
    dynArray2 := Copy(dynArray1, 0, high(dynArray1));
wenn ich dann aber die beiden Arrays mit:
Delphi-Quellcode:
    FOR i := 1 TO high(dynArray1) DO
     begin
      ShowMessage(dynArray1[i].textinhalt + ' vs. ' + dynArray2[i].textinhalt);
     end;
vergleiche, dann steht beim letzten Element immer "text123 vs. [komische Zeichen]"

also scheinbar wird das letzte Element nicht kopiert ?! :?:

hat jemand ein Tipp, was ich falsch mache? :wink:
oder eine andere/bessere Möglichkeit dyn. Arrays zu kopieren? (aber muss eine richtige Kopie sein, nicht nur Reference)

SirThornberry 7. Mär 2010 10:43

Re: dynamische Array kopieren (letztes Element fehlt)
 
dynamische Arrays beginnen immer bei 0. Ein dynamisches Array mit 3 Elementen geht also von yourarray[0] bis yourarray[2]

[Edit]
Herzlich Willkommen in der Delphi-Praxis :dp:

brainless 7. Mär 2010 10:53

Re: dynamische Array kopieren (letztes Element fehlt)
 
(hatte oben noch einen kleinen Fehler drin bei der ersten FOR-Schleife)

Zitat:

Zitat von SirThornberry
Herzlich Willkommen in der Delphi-Praxis :dp:

danke :)

Zitat:

Zitat von SirThornberry
dynamische Arrays beginnen immer bei 0. Ein dynamisches Array mit 3 Elementen geht also von yourarray[0] bis yourarray[2]

ja aber high(dynArray1) müsste doch dann genau das letzte Element erwischen ,oder?
also im Prinzip wird bei mir oben doch nur überall das erste Element (yourarray[0]) übersprungen? bzw. bleibt leer

das erlkärt noch nicht das Fehlen des letzten Element ,oder? :?:

himitsu 7. Mär 2010 10:57

Re: dynamische Array kopieren (letztes Element fehlt)
 
Es gibt zwar eine Refferenzzählung bei dynamischen Arrays, welche manchmal ihre Probleme hat.
Sonst würde man mit Folgendem keine Probleme haben.
Delphi-Quellcode:
dynArray2 := dynArray1;
Vorallem wird "leider" nicht vor dem Zuweisen eines Wertes geprüft, ob es eine Singleinstanz ist und somit werden die Werte direkt und somit auch aller gleichen Instanzen geändert.

Delphi-Quellcode:
dynArray2 := Copy(dynArray1);
sorgt dafür, daß es danach eine Einzelinstanz ist.
Sowas wie UniqueString gibt es leider nur für Strings (welche allerdings auch "nur" 'ne Sonderform von dynamischen Char-Arrays sind.

brainless 7. Mär 2010 11:11

Re: dynamische Array kopieren (letztes Element fehlt)
 
Delphi-Quellcode:
dynArray2 := dynArray1;
dann bekomme ich die folgende Fehlermeldung:
Zitat:

[Fehler] Uliste.pas(301): Inkompatible Typen
obwohl beide Arrays vom selben Typ sind: (siehe 1. Beitrag)
Delphi-Quellcode:
procedure TForm_liste.BtnSortClick(Sender: TObject);
var i, j: Integer;
// ...
    dynArray1: array of TIrgendwas;
    dynArray2: array of TIrgendwas;
begin

Luckie 7. Mär 2010 11:15

Re: dynamische Array kopieren (letztes Element fehlt)
 
Nein, sind sie nicht.
Delphi-Quellcode:
type
  TMyDynArray = array of Integer;

var
  dynarray1: TMyDynArray;
  dynarray2: TMyDynArray;
Jetzt sind sie vom gleichen Typ.

himitsu 7. Mär 2010 11:17

Re: dynamische Array kopieren (letztes Element fehlt)
 
Delphi ist da sehr strikt und es sind zwar ähnliche, aber nicht die selben Typen.

Delphi-Quellcode:
var dynArray1, dynArray2: array of TIrgendwas;
Delphi-Quellcode:
type TIrgendwasArray = array of TIrgendwas;
var dynArray1, dynArray2: TIrgendwasArray;
Delphi-Quellcode:
type TIrgendwasArray = array of TIrgendwas;
var dynArray1: TIrgendwasArray;
  dynArray2: TIrgendwasArray;

samso 7. Mär 2010 11:25

Re: dynamische Array kopieren (letztes Element fehlt)
 
Der Befehl copy kopiert meines Wissens nicht von x bis y sondern ab x soundsoviel Elemente. Also müsste es
Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, Length(dynArray1));
lauten, damit alle Elemente kopiert werden, oder?

Luckie 7. Mär 2010 11:33

Re: dynamische Array kopieren (letztes Element fehlt)
 
Nicht Length()-1?

brainless 7. Mär 2010 11:35

Re: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von samso
Der Befehl copy kopiert meines Wissens nicht von x bis y sondern ab x soundsoviel Elemente. Also müsste es
Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, Length(dynArray1));
lauten, damit alle Elemente kopiert werden, oder?

jap das stimmt ;)
aber selbst wenn ich High(...)+1 nehme (was ja dann das selbe wie Length(...) ist, fehlt das letzte Element

-----

ich dachte immer, dass das:
var dynArray1, dynArray2: TIrgendwasArray;
das selbe wie das ist:
dynArray1: array of TIrgendwas;
dynArray2: array of TIrgendwas;

:o

okay wenn ich jetzt
Delphi-Quellcode:
dynArray2 := dynArray1;
benutze, sind alle dynArrayX[i].textinhalt aufeinmal leer? :?

Edit: hmm habe 1 und 2 verwechselt .. okay danke es klappt :thumb:

himitsu 7. Mär 2010 11:37

Re: dynamische Array kopieren (letztes Element fehlt)
 
Length(arr)-1 = High(arr) ... bei einem dynamischem Array

Und jupp, es ist Copy(source, start, len).

Zitat:

Zitat von brainless
Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, high(dynArray1));
FOR i := 1 TO high(dynArray1) DO
begin
  ShowMessage(dynArray1[i].textinhalt + ' vs. ' + dynArray2[i].textinhalt);
end;

Schalte mal die Bereichsprüfung in den Projektoptionen an.

brainless 7. Mär 2010 11:38

Re: dynamische Array kopieren (letztes Element fehlt)
 
edit

uligerhardt 7. Mär 2010 11:42

Re: dynamische Array kopieren (letztes Element fehlt)
 
Man iteriert über alle eingebauten Delphi-Arrays, egal ob statisch, dynamisch, offen oder sonstwie, per
Delphi-Quellcode:
Low(arr) to High(arr)
, und schon passt's.

himitsu 7. Mär 2010 11:49

Re: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von uligerhardt
Man iteriert über alle eingebauten Delphi-Arrays, egal ob statisch, dynamisch, offen oder sonstwie, per
Delphi-Quellcode:
Low(arr) to High(arr)
, und schon passt's.

Delphi-Quellcode:
//var el: telement;
//  arr: array of telement;

for el in arr do
:angel2:

uligerhardt 7. Mär 2010 11:55

Re: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von himitsu
Delphi-Quellcode:
//var el: telement;
//  arr: array of telement;

for el in arr do
:angel2:

Oder so - hab ich ganz vergessen. :lol:
Leider ist das for-in manchmal nicht gerade effizient, wenn man es mit "herkömmlichen" for-Schleifen vergleicht. Bei Schleifen über Sets und Arrays ist das aber WIMRE nicht so. Muss ich glatt bei Gelegenheit noch mal checken.

samso 7. Mär 2010 12:38

Re: dynamische Array kopieren (letztes Element fehlt)
 
Mit
Delphi-Quellcode:
dynArray2 := dynArray1;
wird aber nur die Referenz kopiert. Wenn man nun
Delphi-Quellcode:
  dynArray2[0] := IrgendwasNeues;
setzt, wird auch dynArray1[0] geändert! (Anderes als bei Strings). Das Kopieren der Referenz ist nicht das gleiche, wie der Copy-Befehl. Nur beim Copy-Befehl wird der komplette Inhalt kopiert.

Die Delphi-Hilfe dazu:

Zitat:

Wenn X und Y Variablen desselben dynamischen Array-Typs sind, führt die Anweisung X := Y dazu, dass X auf dasselbe Array wie Y zeigt. (Es ist nicht erforderlich, vor dieser Operation Speicher für X zu reservieren.) Im Gegensatz zu Strings und statischen Arrays wird copy-on-write nicht für dynamische Arrays verwendet. Deshalb werden diese nicht automatisch kopiert, bevor einem ihrer Elemente ein Wert zugewiesen wird.

brainless 7. Mär 2010 13:18

Re: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von samso
Mit
Delphi-Quellcode:
dynArray2 := dynArray1;
wird aber nur die Referenz kopiert. Wenn man nun
Delphi-Quellcode:
  dynArray2[0] := IrgendwasNeues;
setzt, wird auch dynArray1[0] geändert! (Anderes als bei Strings). Das Kopieren der Referenz ist nicht das gleiche, wie der Copy-Befehl. Nur beim Copy-Befehl wird der komplette Inhalt kopiert.

stimmt. genau das Problem habe ich jetzt :| also statt dynArray2 := dynArray1; dann doch wieder dynArray2 := Copy(dynArray1); aber dann fehlen wieder Elemente am Ende :wall:

Edit: ich weiß nicht, wo der Fehler war.. aber jetzt funktioniert es auf einmal mit
Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, High(dynArray1) + 1);
:gruebel: (danke allen) :thumb:

himitsu 7. Mär 2010 14:00

Re: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von brainless
stimmt. genau das Problem habe ich jetzt :| also statt dynArray2 := dynArray1; dann doch wieder dynArray2 := Copy(dynArray1); aber dann fehlen wieder Elemente am Ende :wall:

kann nicht sein, denn dieses kopiert alles.

Edit: ich weiß nicht, wo der Fehler war.. aber jetzt funktioniert es auf einmal mit
Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, High(dynArray1) + 1);
:gruebel: (danke allen) :thumb:[/quote]

Delphi-Quellcode:
dynArray2 := Copy(dynArray1, 0, Length(dynArray1));
oder eben
Delphi-Quellcode:
dynArray2 := Copy(dynArray1);

QuickAndDirty 25. Sep 2018 13:55

AW: dynamische Array kopieren (letztes Element fehlt)
 
Nur mal so am rande bedeutet das, dass folgendes das selbe macht
Delphi-Quellcode:
Procedure Main;
  var Keys:TStringDynArray;

  Procedure KeyFooRef(var arr:TStringDynArray)//MIT VAR
  Begin
    Setlength(arr,4);
    arr[0] := 'Das';
    arr[1] := 'ist';
    arr[2] := 'ein';
    arr[3] := 'Test';
  end;

  Procedure KeyFooVal(arr:TStringDynArray)// OHNE VAR
  Begin
    Setlength(arr,4);
    arr[0] := 'Das';
    arr[1] := 'ist';
    arr[2] := 'ein';
    arr[3] := 'Test';
  end;

Begin
  KeyFooRef(Keys);//Fall 1
  KeyFooVal(Keys);//Fall 2
end;

uligerhardt 25. Sep 2018 14:09

AW: dynamische Array kopieren (letztes Element fehlt)
 
Zitat:

Zitat von QuickAndDirty (Beitrag 1414130)
Nur mal so am rande bedeutet das, dass folgendes das selbe macht

Nö - probier's doch einfach mal aus. Bei Fall 2 wird zwar innerhalb von KeyFooVal die Kopie "arr" verändert, nicht aber das Original "Keys" aus Main.
So sieht man's vielleicht deutlicher:
Delphi-Quellcode:
procedure Main;
var
  Keys: TStringDynArray;

  procedure KeyFooRef(var arr: TStringDynArray); //MIT VAR
  begin
    Setlength(arr, 4);
    arr[0] := 'Das';
    arr[1] := 'ist';
    arr[2] := 'ein';
    arr[3] := 'Test';
  end;

  procedure KeyFooVal(arr: TStringDynArray); // OHNE VAR
  begin
    Setlength(arr, 4);
    arr[0] := 'Das';
    arr[1] := 'ist';
    arr[2] := 'ein';
    arr[3] := 'Test';
  end;

  procedure Raus(AIndex: Integer; const arr: TStringDynArray);
  var
    i: Integer;
  begin
    Write(AIndex, ':');
    for i := Low(arr) to High(arr) do
      Write(' ', arr[i]);
    Writeln;
  end;

begin
  Raus(1, Keys);
  KeyFooRef(Keys); //Fall 1
  Raus(2, Keys);
  Keys := nil;
  Raus(3, Keys);
  KeyFooVal(Keys); //Fall 2
  Raus(4, Keys);
end;

freimatz 25. Sep 2018 14:23

AW: dynamische Array kopieren (letztes Element fehlt)
 
Weils hier öfters ein Problem war: http://www.selbe-gleiche.de/

himitsu 25. Sep 2018 17:58

AW: dynamische Array kopieren (letztes Element fehlt)
 
Ihr müsst bei "ohne var" das SetLength weglassen,
denn Dieses behandelt ordnungsgemäß die Referenzzählung und macht vor dem nachfolgenden Schreibzugriff die lokale "Kopie" unique.
Mit "const" würde die Referenz nicht hochgezählt, was bei SetLength dann durchrutschen würde (wenn vor Funktionsaufruf nur eine Referenz existierte), aber da SetLength bei einer Kostante vom Compiler verweigert wird, gibt es dieses Problem dort nicht.

Grund: außer bei LongStrings funktioniert für keine dynamischen Array die Referenzprüfung, wenn auf Felder schreibend zugegriffen wird.
CopyOnWrite ist da nur für LongStrings (String, AnsiString, UnicodeString usw.) implementiert und fehlt seit Jahrzehnten.

PS:
Delphi-Quellcode:
A2 := A1;
und übergabe an Parameter/Property erhöht nur den Referenzzähler.
Delphi-Quellcode:
A2 := Copy(A2);
, SetLength oder die UniqueXyz-Funktionen aus der System-Unit sollte man also vor Schreibzugriffen immer manuell aufrufen, wenn man mit "externen" Arrays arbeitet und deren Inhalt nicht veränder darf.




PSS: Noch ein Beispiel, dass auch LongStrings nicht von Problemen verschont werden.
Delphi-Quellcode:
function MeineFunktion: string;
begin
  Result := Result + 'X';
end;

S := '';
for i := 1 to 10 do
  S := MeineFunktion;
ShowMessage(S);

QuickAndDirty 26. Sep 2018 09:55

AW: dynamische Array kopieren (letztes Element fehlt)
 
Bitte sagt mir ob ich das richtig verstanden habe!

Also wird tatsächlich immer eine Referenz auf ein DynArray übergeben.
Abhängig von dem was ich danach mit der Referenz des Dnyarray mache wird unterschiedlicher Maschinencode erzeugt.

Im
Code:
 procedure KeyFooVal(arr: TStringDynArray)
Fall, wird erst beim schreiben durch "Copy on Write" eine Arbeitskopie angelegt.
Wenn ich nur lesend auf das Dynarray zugreife dann lese ich vom referenzierten Original?
Das Schreiben auf Elementen des DynArray gilt nicht als Schreibenderzugriff auf das DynArray. "Copy on Write" erfolgt nicht.
SetLength gilt als Schreiben auf das DynArray "copy on Write" erfolgt.

Im
Code:
procedure KeyFooRef(var arr: TStringDynArray);
Fall, wird auch eine Referenz übergeben aber in keinem Fall erfolgt ein "Copy on write" wenn das DynArray bearbeitet wird.

>"This is madness!"


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:25 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