Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Größenveränderung bei dyn. Arrays auf Pointerbasis (https://www.delphipraxis.net/76402-groessenveraenderung-bei-dyn-arrays-auf-pointerbasis.html)

MStoll 3. Sep 2006 22:45


Größenveränderung bei dyn. Arrays auf Pointerbasis
 
Hallo

derzeit bin ich dabei, Array-Operationen (Sortieren, Austauschen, Vergleichen, Löschen, Einfügen) zu verallgemeinern, indem ich Prozeduren schreiben, denen ich ein dyn. Array als Zeiger übergebe (Siehe auch bei den Vorschlägen zur Code-Library, Thread "Shellsort für beliebige Arrays"). Sortieren, Austauschen und Vergleichen (bei statischen Typen!) geht soweit ganz gut allgemein, da sie keine Größenveränderungen am Array verursachen. Hab auch schon ne Basis für eine Lösch-Prozedur. Allerdings will es mir nicht gelingen, dabei die Größe des Arrays innerhalb der Prozedur zu verändern. Deshalb muss ich das immer so aufrufen:
Delphi-Quellcode:
ArrDelete(Arr, Length(Arr), SizeOf(Arr), idx);
SetLength(Arr, Length(Arr)-1);
Die ArrDelete-Prozedur sieht so aus:
Delphi-Quellcode:
procedure Exch(P : Pointer; ElSize : integer; a, b : integer);
var P1, P2 : Pointer;
    B1 : byte;
    x : integer;
begin
     P1 := Pointer(Integer(P) + ElSize * a);
     P2 := Pointer(Integer(P) + ElSize * b);
     
     for x := 0 to ElSize-1 do
     begin
          b1 := Byte(Pointer(Integer(P1)+x)^);
          Byte(Pointer(Integer(P1)+x)^) := Byte(Pointer(Integer(P2)+x)^);
          Byte(Pointer(Integer(P2)+x)^) := b1;
     end;
end;

procedure ArrDelete(P : Pointer; Size, ElSize, Idx : integer);
var x : integer;
begin
     if (Idx < 0) or (Idx >= Size) then
        exit;

     for x := Idx to Size-2 do
         Exch(P, ElSize, x, x+1);
end;
Ich würde nun gern letzteres SetLength irgendwie in die ArrDelete-Prozedur mit reintun.

Hat jemand eine Idee?

Danke
Michael

mkinzler 4. Sep 2006 07:18

Re: Größenveränderung bei dyn. Arrays auf Pointerbasis
 
Verwende lieber var-Paramter statt den pointern, dann solte es funktionieren.
BTW. Dynamische Array sind eigentlich schon Pointer.

MStoll 4. Sep 2006 08:02

Re: Größenveränderung bei dyn. Arrays auf Pointerbasis
 
und welchen Typ soll dieser var-Parameter haben? Ich habe genau deshalb Pointer gewählt, um JEDEN Array-Typ verarbeiten zu können. Wie das speziell für die einzelnen Array-Typen geht, weiß ich ja...

himitsu 4. Sep 2006 11:28

Re: Größenveränderung bei dyn. Arrays auf Pointerbasis
 
Etwa so?
Delphi-Quellcode:
Type TIntegerArray = Array of Integer;
  PIntegerArray = ^TIntegerArray;

SetLength(TIntegerArray(P), 123);
// oder
SetLength(PIntegerArray(P)^, 123);


//zusammen mit Length dann so
//(wobei man in der Längenangabe auch einen Standardarraytyp
//verwenden kann, da die Längengabe nicht vom Arraytyp abhängig ist)
SetLength(TIntegerArray(P), Length(TIntegerArray(P)) - 1);
SetLength(TIntegerArray(P), High(TIntegerArray(P)));
SetLength(TIntegerArray(P), (PInteger(P) - 4)^ - 1);

MStoll 4. Sep 2006 19:25

Re: Größenveränderung bei dyn. Arrays auf Pointerbasis
 
Das funktioniert leider nicht, da gibt's den Fehler "Ungültige Zeigeroperation". Wenn ich z.B. ein array of extended als TByteArr caste und dann in dieser Prozedur mit SetLength die Größe ändere, wird außerdem alles genullt, was hinter der Grenze zur ursprünglichen Länge liegt. Schwer zu erklären, daher ein Beispiel:

Delphi-Quellcode:
type TByteArr = array of byte;
procedure ArrDelete(var P : TByteArr; Size, ElSize, Idx : integer);
begin
     // ...
     SetLength(P, Length(P)-1);            // So werden nur 19 statt der für extended-arr nötigen 190 Bytes reserviert
     SetLength(P, (length(P)-1) * ElSize); // So werden zwar 190 Bytes reserviert, allerdings ist Length(P) dann zu groß
                                            // außerdem wird alles nach Byte Nr. 20 gelöscht
end;

procedure test;
var a : array of extended;
begin
     SetLength(a, 20);
     ArrDelete(TByteArr(a), Length(a), SizeOf(a[0]), 2);

     // dann "Ungültige Zeigeroperation
     // ...
end;
Hast du das schonmal ausprobiert, was du sagst? Wenn ja, könntest du bitte ein compilier- und lauffähiges Stück Code posten?


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:17 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz