Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Aus Dynamischen Array Hersusschneiden. (https://www.delphipraxis.net/76366-aus-dynamischen-array-hersusschneiden.html)

shifter 3. Sep 2006 06:33


Aus Dynamischen Array Hersusschneiden.
 
:oops:

Wie kann ich ein Teil aus dem Dynamischen Array Heraus schneiden und den Rest nachrücken ??

Delphi-Quellcode:
Var
  a : Array of irgen ein Record
  b : Byte;
Begin
  SetLength( a, 5 );
  For b:=0 To 4 Do a[b]:=b
So und jetzt möchte ich den wert aus der Position Nr. 2 Herausschneiden
und das Ergebnis Soll So Aussehen

0,2,3,4



Danke

gruss
seba

fwsp 3. Sep 2006 06:35

Re: Aus Dynamischen Array Hersusschneiden.
 
ich würde ein temporäres array zu hilfe nehmen, die werte darin zwischenspeichern und dann wieder ins original array packen.

shifter 3. Sep 2006 06:51

Re: Aus Dynamischen Array Hersusschneiden.
 
Hi,

da dran habe ich auch überlegt, aber es könnte vieleich viel zu Zeitaufwendig sein bei grösseren sachen.

Ich dachte vieleicht bibts es eine einfachere metode.

gruss
seba

Daniel B 3. Sep 2006 08:10

Re: Aus Dynamischen Array Hersusschneiden.
 
Kannst die Daten ja nachrücken ohne extriges Array.

Wenn du z.B. 1, 2, 3, 4, 5, hast und löscht 2 und 3, dann kopierst du 4 nach zwei, 5 nach drei und kürzt dann das Array um zwei.

shifter 3. Sep 2006 09:11

Re: Aus Dynamischen Array Hersusschneiden.
 
Ja das werde ich jetzt versuchen

danke

alzaimar 3. Sep 2006 09:26

Re: Aus Dynamischen Array Hersusschneiden.
 
Delphi-Quellcode:
Procedure DeleteFromArray (anArray : Array Of <MyType>; anIndex : Integer);
Var
  BytesPerElement,
  TotalBytesToMove : Integer;

Begin
  BytesPerElement := Sizeof (anArray [0]);
  TotalBytesToMove := (Length (anArray) - anIndex + 1)* BytesPerElement;
  If TotalBytesToMove > 0 Then
    Move (anArray [anIndex + 1], anArray [anIndex], TotalBytsToMove);  
End;

Hawkeye219 3. Sep 2006 09:45

Re: Aus Dynamischen Array Hersusschneiden.
 
Hallo alzaimar,

du bist zu schnell, ich war mit meinem Code doch noch gar nicht fertig

Drei Korrekturen:
- das Array sollte noch mit SetLength() verkürzt werden
- wg. SetLength muß anArray als VAR-Parameter übergeben werden
- bei der Berechnung von TotalBytesToMove muß die 1 subtrahiert werden

Hier mein Code (hoffentlich fehlerfrei):

Delphi-Quellcode:
type
  TMyRec = record
    x, y : Integer;
    s   : string;
  end;

  TDynMyRecArray = array of TMyRec;

// Entfernt aCount Elemente ab Index aStart aus dem dynamischen Feld aArray
procedure RemoveItem (var aArray: TDynMyRecArray; aStart: Integer; aCount: Integer = 1);
begin
  // Startindex auf Gültigkeit prüfen
  if (aStart >= 0) and (aStart <= High(aArray)) then
    begin
      // Anzahl prüfen und ggf. korrigieren
      if (aStart + aCount > Length(aArray)) then
        aCount := Length(aArray) - aStart;
      // Elemente hinter zu löschendem Bereich nach vorne schieben
      if (aStart + aCount < Length(aArray)) then
        Move (aArray[aStart + aCount], aArray[aStart],
              (Length(aArray) - (aStart + aCount)) * SizeOf(aArray[0]));
      // Arraylänge anpassen
      SetLength (aArray, Length(aArray) - aCount);
    end;
end;

procedure Test;
var
  A : TDynMyRecArray;
begin
  SetLength (A, 5);
  ...
  RemoveItem (A, 2);    // entfernt das Element A[2]
  RemoveItem (A, 0, 2); // entfernt die Elemente A[0] und A[1]
end;
Noch ein Hinweis: wenn der Record Referenzen auf Objekte enthält, müssen diese vor dem Aufruf von RemoveItem manuell freigegeben werden. Für Interfaces oder dynamische Strukturen erledigt dies die Prozedur SetLength.

Gruß Hawkeye

shifter 3. Sep 2006 11:42

Re: Aus Dynamischen Array Hersusschneiden.
 
Danke für Eure Antworten,
das hat alles ganz schön funktioniert.

Aber mal andere frage die eingentlich auch hier gehören könnte.

Wenn ich jetzt ein Dyn.Array habe wie z.B.
Delphi-Quellcode:
Var
  a : Array of MyRecord;
...
und diesen beenden möchte mit :
Delphi-Quellcode:
  Finalize( a , Length( a ));
  SetLength( a, 0 );
Bekomme ich eine Speicher verletztung !

Wenn ich es mit
Delphi-Quellcode:
 a := nil;
Wird mein Reservierte Speicher nicht freigegeben.

Also wie soll ich es Beenden ?

Gruss

Hawkeye219 3. Sep 2006 12:00

Re: Aus Dynamischen Array Hersusschneiden.
 
Hallo shifter,

bei einem Verkleinern dynamischer Arrays durch SetLength wird automatisch für die freigegebenen Elemente ein Finalize durchgeführt. Wenn du es trotzdem aufrufen möchtest, dann so:

Delphi-Quellcode:
Finalize (a[0], Length(a));
Auch das Löschen dynamischer Arrays über eine Zuweisung von NIL führt zu einem Finalize-Aufruf. Dabei werden aber immer nur dynamische Strings oder Arrays sowie Interface-Zeiger behandelt. Objekte, zu denen du Referenzen im Record abgelegt hat, muß du selbst durch einen Aufruf ihrer Free-Methode freigeben.

Gruß Hawkeye

shifter 3. Sep 2006 12:47

Re: Aus Dynamischen Array Hersusschneiden.
 
Ja ,
jetzt sieht es viell besser aus.

Aber trotz dem wenn ich mir mit dem TaskManager den Speicher verbrauch mal angucke vor dem
ich den Dyn.Array erstelle und nach dem ich Ihm auflöse bekomme ich nicht mehr den alten wert.

Also wenn ich die Aktion ein paar mal wiederhole verbraucht mein Proggi immer mehr Speicher.

Vieleich mal zu den Record,
er besteht aus ein paar Integers, und TBitmaps.

Die TBitmaps werden am Ende mit Free freigegeben 8und am Ende habe ich so gemach wie Du mir das
geschrieben hast also mit
Delphi-Quellcode:
  Finalize ( a[0], Length(a));
Warum bekomme ich nicht den alten zustand wieder her ?

gruss
seba

Hawkeye219 3. Sep 2006 13:30

Re: Aus Dynamischen Array Hersusschneiden.
 
Verlasse dich nicht allzu sehr auf die Anzeige im Taskmanager. Der MemoryManager von Delphi könnte die Speicherblöcke durchaus noch reserviert haben, um sie bei nachfolgenden Anforderungen wieder zur Verfügung zu stellen. In diesem Fall wird sich der angezeigte Wert im Taskmanager kaum ändern.

Einen Hinweis auf tatsächliche MemLeaks erhältst du, wenn du die Projektdatei folgendermaßen erweiterst:

Delphi-Quellcode:
begin
  {$WARN SYMBOL_PLATFORM OFF}                       // <<-- diese Zeile hinzufügen
  ReportMemoryLeaksOnShutdown := (DebugHook <> 0); // <<-- diese Zeile hinzufügen
  Application.Initialize;
  ...
end.
Wenn du jetzt dein Programm in der Delphi-IDE laufen läßt, erscheint beim Beenden eine Dialogbox mit Hinweisen auf MemLeaks, sofern welche vorhanden sind. Besonders informativ ist die Anzeige leider nicht. Sie zeigt nur an, daß nicht alle angeforderten Speicherblöcke zurückgegeben wurden, aber nicht, wo dies passiert. Um diese Stellen zu finden, wirst du andere Werkzeuge einsetzen müssen. In der DP gibt es einige Threads zu diesem Thema.

Gruß Hawkeye

shifter 3. Sep 2006 19:07

Re: Aus Dynamischen Array Hersusschneiden.
 
Danke für Dein Tip,

ich habe exack so wie du es beschrieben gemacht,
leider bekomme ich nichts raus, also kein DialogBox oder ne meldung.

seba

Flare 3. Sep 2006 19:49

Re: Aus Dynamischen Array Hersusschneiden.
 
Zitat:

Zitat von Hawkeye219
..., sofern welche vorhanden sind.

Dann sind höchstwahrscheinlich keine MemLeaks vorhanden :zwinker:

Flare

Neutral General 3. Sep 2006 19:57

Re: Aus Dynamischen Array Hersusschneiden.
 
Also ich weiß nicht obs schon gesagt wurde aber ich mache es einfach so:

Delphi-Quellcode:
procedure DeleteItem(var AArray: TArrayofKa; Index: Integer);
var tmp: TArrayofKa;
    i,j: Integer;
begin
  j:= 0;
  SetLength(tmp,Length(AArray)-1);
  for i:= 0 to High(AArray) do
   if i <> Index then
   begin
    tmp[j] := AArray[i];
    inc(j);
   end;
   AArray := tmp;
end;
So in etwa :stupid:

Gruß
Neutral General

Khabarakh 3. Sep 2006 20:58

Re: Aus Dynamischen Array Hersusschneiden.
 
Da finde ich Move aber ein wenig eleganter :zwinker: .

MStoll 3. Sep 2006 22:32

Re: Aus Dynamischen Array Hersusschneiden.
 
Hallo

Warum so kompliziert?

Delphi-Quellcode:
procedure delete_arr_item(var arr : tbyte_arr; idx : integer); overload;
var x : integer;
begin
     for x := idx + 1 to high(arr) do
         arr[x-1] := arr[x];
     SetLength(arr, length(arr) - 1)
end;
Ist vll nicht die schnellste, aber sicher eine der kürzesten Varianten.

[Edit]Allerdings lässt sie alle Elemente "in Ruhe", die eh nicht verändert werden (d.h. die mit einem Index < als idx)[/Edit]

Gruß
Michael


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