SetLength bei Parameter

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Weizenbaum
Beiträge: 28
Registriert: Mi 24. Aug 2016, 09:00

SetLength bei Parameter

Beitrag von Weizenbaum »

Hallo zusammen,
ich übergebe einer Prozedur ein leeres dynamisches Array, welche das mit Daten füllen soll. Allerdings scheitert es schon bei SetLength leider.

Code: Alles auswählen

// Übergabe Array mit Daten füllen
procedure TDBKostenkontrolle.GetPListe(var argListe: array of recPosten);
var
  iCount: integer;
begin
  for iCount:= 0 to Length(PListe)-1 do
  begin
    SetLength(argListe, Length(argListe)+1);
    argListe[High(argListe)].rBetrag:= PListe[iCount].rBetrag;
    argListe[High(argListe)].sBezeichnung:= PListe[iCount].sBezeichnung;
  end;
end;
Weiß jemand, wie ich die Größe des dynamischen Arrays ändern kann?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: SetLength bei Parameter

Beitrag von af0815 »

ist argListe schon einmal Initialisiert ?
wenn nicht, so einmal mit

Code: Alles auswählen

// Übergabe Array mit Daten füllen
procedure TDBKostenkontrolle.GetPListe(var argListe: array of recPosten);
var
  iCount: integer;
begin
  // Alten Inhalt löschen
  SetLength(argListe,0);
  // Neu länge kalkulieren und setzen
  //   SetLength ist relativ teuer in der Ausführung 
  SetLength(argListe, Length(PListe));
  for iCount:= 0 to Length(PListe)-1 do
  begin
    argListe[High(argListe)].rBetrag:= PListe[iCount].rBetrag;
    argListe[High(argListe)].sBezeichnung:= PListe[iCount].sBezeichnung;
  end;
end;
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Weizenbaum
Beiträge: 28
Registriert: Mi 24. Aug 2016, 09:00

Re: SetLength bei Parameter

Beitrag von Weizenbaum »

Im Hauptprogramm ja, also wo diese Prozedur aufgerufen wird.
Bei SetLength erhalte ich die Fehlermeldung "Type mismatch".
Die Variante außerhalb der Schleife schon die Länge festzulegen finde ich gut. Bin da garnicht drauf gekommen.

Das hier hab ich noch vergessen zu erwähnen, vielleicht hilft das als Zusatzinfo zu "Type mismatch"

Code: Alles auswählen

type
  recPosten = record
    sBezeichnung: string;
    rBetrag: real;
  end;

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: SetLength bei Parameter

Beitrag von af0815 »

Weizenbaum hat geschrieben:
So 21. Feb 2021, 09:47
Das hier hab ich noch vergessen zu erwähnen, vielleicht hilft das als Zusatzinfo zu "Type mismatch"

Code: Alles auswählen

type
  recPosten = record
    sBezeichnung: string;
    rBetrag: real;
  end;
Das ist kein (dyn.) Array, das ist nur der Record. Sowas hätte ich erwartet: argListe = array of recPosten; Falls du argListe = array[0..100] of recPosten hast, so ist das nicht dynamisch.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Weizenbaum
Beiträge: 28
Registriert: Mi 24. Aug 2016, 09:00

Re: SetLength bei Parameter

Beitrag von Weizenbaum »

Das Array ist dynamisch.

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: SetLength bei Parameter

Beitrag von kupferstecher »

Hallo Weizenbaum,

das ist etwas unglücklich gelöst bei FreePascal. Du musst den Übergabeparameter als eigenen Typ definieren, dann funktioniert es. Mit "array of" direkt in der Parameterliste erwartet der Kompiler ein konstantes Array.

Also

Code: Alles auswählen

Type TRecArray = Array of recPosten;

procedure TDBKostenkontrolle.GetPListe(var argListe: TRecArray);
anstatt

Code: Alles auswählen

procedure TDBKostenkontrolle.GetPListe(var argListe: array of recPosten);

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: SetLength bei Parameter

Beitrag von theo »

Hintergrund hier:
http://rvelthuis.de/articles/articles-openarr.html
Insb. auch bei "Confusion".
Ist zwar für Delphi, aber passt schon.

Weizenbaum
Beiträge: 28
Registriert: Mi 24. Aug 2016, 09:00

Re: SetLength bei Parameter

Beitrag von Weizenbaum »

Hallo, hab schon was gefunden im englischen Forum: https://forum.lazarus.freepascal.org/in ... pic=9036.0
Darauf muß man erstmal kommen :D

Code: Alles auswählen

type
  recPosten = record
    sBezeichnung: string;
    rBetrag: real;
  end;
  DefArgListe = array of recPosten;
So sieht nun meine Lösung aus. Ich hatte das Problem schonmal, aber war zu lange her und habe das vergessen.
Ich danke euch trotzdem für eure Antworten.
Naja, jede Sprache hat halt so ihre Eigenheiten.

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: SetLength bei Parameter

Beitrag von PascalDragon »

Weizenbaum hat geschrieben:
So 21. Feb 2021, 08:33

Code: Alles auswählen

procedure TDBKostenkontrolle.GetPListe(var argListe: array of recPosten);
Hiermit deklarierst du einen sogenannten "open array" Parameter. Bei einem solchen kannst du die Länge nicht beeinflussen, nur den Inhalt (wenn du var oder out verwendest).

Für ein dynamisches Array musst du entweder den Typ explizit definieren oder du nimmst den generischen Typ TArray<T> als Hilfe:

Code: Alles auswählen

// mode ObjFPC
procedure TDBKostenkontrolle.GetPListe(var argListe: specialize TArray<recPosten>);
// mode Delphi
procedure TDBKostenkontrolle.GetPListe(var argListe: TArray<recPosten>);
Bitte beachte, dass das erst mit 3.2.0 wirklich zuverlässig funktioniert.
FPC Compiler Entwickler

Antworten