copy mit dynamischen Arrays

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

copy mit dynamischen Arrays

Beitrag von RSE »

Hallo!

Laut http://www.freepascal.org/docs-html/rtl ... /copy.html" onclick="window.open(this.href);return false; kann man copy auch mit dynamischen Arrays benutzen. Wenn ich aber

Code: Alles auswählen

procedure Delete(var ways: array of TWay; way: TWay);
  var
    i: Integer;
  begin
    for i := 0 to Length(ways)-1 do
      if ways[i] = way then begin
        ways := copy(ways,0,i)+copy(ways,i+1,MaxInt);
        Exit;
      end;
  end;
auführen möchte, dann erhalte ich folgende Fehlermeldung:
Error: Incompatible type for arg no. 1: Got "Open Array Of TWay", expected "ShortString"

Mein Kopf (es ist ein einfaches Freepascal-Programm, keine Application):

Code: Alles auswählen

program project1;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, FileUtil, Crt, Math, SysUtils;
 
{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}
Was mache ich falsch, bzw. welche Unit fehlt hier?

Vielen Dank im Voraus
RSE
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: copy mit dynamischen Arrays

Beitrag von mse »

Dies ist kein dynamisches Array sondern ein offener array parameter. Mit dynamischem Array würde es etwa so aussehen:

Code: Alles auswählen

type
 wayarty = array of tway;
 
procedure Delete(var ways: wayarty; way: TWay);
[...]

Für

Code: Alles auswählen

ways := copy(ways,0,i)+copy(ways,i+1,MaxInt);
musst du vermutlich noch einen überladenen "+" operator schreiben.

Martin

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von Scotty »

Wieso nicht per TList? Dort gäbe es das delete() gratis 8)

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von RSE »

Ob nun dynamisches Array oder offener Array Parameter is mir eigentlich wurscht, bis zum "+" ist er auch noch nicht gekommen. Da er aber nun das Copy und das "+" nicht kann, werde ich es anders machen. TList verwende ich nicht, weil es so viel Ballast mitbringt. Ich brauche momentan ein extrem schlankes Programm.

TList macht es so:

Code: Alles auswählen

procedure TFPList.Delete(Index: Integer);
begin
  If (Index<0) or (Index>=FCount) then
    Error (SListIndexError, Index);
  FCount := FCount-1;
  System.Move (FList^[Index+1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
  // Shrink the list if appropriate
  if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  begin
    FCapacity := FCapacity shr 1;
    ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  end;
end;
Demnach würde wohl meine Prozedur folgendermaßen funktionieren (zumindest compilieren tut er so):

Code: Alles auswählen

type
  TWayArray = array of TWay;
//...
procedure Delete(var ways: TWayArray; const way: TWay);
  var
    i: Integer;
  begin
    for i := 0 to Length(ways)-1 do
      if ways[i] = way then begin
        System.Move(ways[i+1],ways[i],((Length(ways)-i)-1)*SizeOf(Pointer));
// TWay ist eine Klasse, somit sind die Einträge von ways Pointer auf die jeweilige Instanz
// Die Instanz selbst wird anderweitig freigegeben ;-)
        SetLength(ways,Length(ways)-1);
        Exit;
      end;
  end;
Zuletzt geändert von RSE am Mo 18. Mai 2009, 12:01, insgesamt 1-mal geändert.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Linkat
Lazarusforum e. V.
Beiträge: 566
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 22.1; Lazarus 4.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 64
Wohnort: nr Stuttgart

Re: copy mit dynamischen Arrays

Beitrag von Linkat »

Hallo RSE,
normalerweise muss die Länge eines dynamischen Arrays mit SetLength noch eingegeben werden.

Gruß, Linkat
Linux Mint 21.3; Lazarus 3.4 FPC 3.2.2; RaspiOS

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von RSE »

Das tue ich nicht mit der Zeile vor "Exit"?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Linkat
Lazarusforum e. V.
Beiträge: 566
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 22.1; Lazarus 4.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 64
Wohnort: nr Stuttgart

Re: copy mit dynamischen Arrays

Beitrag von Linkat »

Hallo RSE,
deinen letzten Beitrag konnte ich nicht lesen, da ich zur gleichen Zeit meinen Beitrag geschrieben habe.
Aber ich denke, der SetLength Befehl muss vorher kommmen. Du benutzt ja length(ways) in deiner for-Schleife, ohne vorher definiert zu haben wie groß das Array ist.

Gruß, Linkat
Linux Mint 21.3; Lazarus 3.4 FPC 3.2.2; RaspiOS

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von RSE »

Die Prozedur benutzt ja offenbar auch nur das Array, es definiert es nicht. Natürlich wurde es vorher mit SetLength vergrößert, als es mit den Ways gefüllt wurde. Ich habe lediglich die Löschung eines beliebigen Elements in eine eigene Prozedur ausgelagert. Vielleicht werde ich es auch inline belassen.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von Scotty »

Okay, mit Classes (also TList) ist ein Minimalprogramm 445kB groß, ohne 128 (jeweils mit strip). Wenn der Unterschied so dramatisch ist... :shock:
Prinzipiell sollte es mit move() gehen. Oder ganz einfach so:

Code: Alles auswählen

procedure Delete(var ways: array of TWay; way: TWay);
  var
    i,j: Integer;
  begin
    for i:=0 to Length(ways)-1 do
      if ways[i] = way then begin
        ways[i].free; //muss sicher auch irgendwo gemacht werden
        for j:=i to length(ways)-2 do 
          ways[j] := ways[j+1];
        setlength(ways,length(ways)-1);
        break;
      end;
  end;
Zu bedenken ist, ob ein einfacher Vergleich ausreicht. Vielleicht brauchst du so was wie CompareMem(). TList ist schon sehr komfortabel :mrgreen:

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von RSE »

Meine exe ist momentan 577KB groß (ohne strip!, mit Zeilennummern, ohne GDB). Ways beinhaltet lediglich zusätzliche Referenzen auf die Instanz. Die Freigabe der Instanz erfolgt anderweitig. Ein einfacher Vergleich wird true, wenn die Zeiger auf den selben Speicherbereich zeigen, also auf die selbe Instanz. Das ist genau das, was ich will. Die Sache mit der for-Schleife fällt einem natürlich als erstes ein, allerdings ist System.Move sicherlich schneller ;-)
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: copy mit dynamischen Arrays

Beitrag von mse »

RSE hat geschrieben:Ob nun dynamisches Array oder offener Array Parameter is mir eigentlich wurscht, bis zum "+" ist er auch noch nicht gekommen. Da er aber nun das Copy und das "+" nicht kann, werde ich es anders machen.
"Er" kann Copy für offene Array Parameter nicht, für dynamische Arrays schon...

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: copy mit dynamischen Arrays

Beitrag von RSE »

Achso... Naja, nun ist es ja anders gelöst.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Antworten