Dynamisches Array von Prozedur übergeben

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
din_iso
Beiträge: 10
Registriert: Sa 11. Mai 2013, 14:09

Dynamisches Array von Prozedur übergeben

Beitrag von din_iso »

Hallo,

wenn ich in einer Prozedur ein Dynamisches Array deklariere, wie folgt:

Code: Alles auswählen

procedure Ausgelagert_1(var arrS: array of String);   
Und jetzt dieses Array in meinem Programm übergeben möchte, in dem es schon deklariert ist, wie stelle ich das an, das er die dynamische Größe übernimmt?

Mit "SetLength(arS , 500);" würde ich die Größe ja nur neu setzen, was mir nicht viel nützt.

Ich hoffe mal Irgenwer weiß Rat...

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Dynamisches Array von Prozedur übergeben

Beitrag von mschnell »

Ich verstehe das Problem nicht.

Die Länge des dynamischen Arrays bleibt bei Übergabe an das Unterprogramm und bei Rück-Übergabe erhalten, auch wenn sie im Unterprogramm geändert wurde. Dazu brauch es nicht einmal ein var-Parameter zu sein, weil ohnehin nur de Pointer übergeben wird. Var rauchst Du nur, wenn du ein anderes Array auf den Parameter zuordnen willst.

-Michael

Benutzeravatar
willi4willi
Lazarusforum e. V.
Beiträge: 167
Registriert: Sa 1. Nov 2008, 18:06
OS, Lazarus, FPC: Windows, Linux (debian) / Lazarus 3.2 / FPC 3.2.2
CPU-Target: i386, win64, arm

Re: Dynamisches Array von Prozedur übergeben

Beitrag von willi4willi »

Hallo,

vielleicht dieses Problem?

Code: Alles auswählen

 
procedure Ausgelagert_1(var arrS: array of String);
begin
  arrS[2]:='Fritz';   // das geht noch
  setlength(arrS,6);  // hier Error: Type mismatch
  arrS[5]:='Erich';
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var  a : array of String;
     i : integer;
begin
  setlength(a,5);
  a[0]:='Otto';
  a[1]:='Otto';
  a[2]:='Otto';
  a[3]:='Otto';
  a[4]:='Otto';
  Ausgelagert_1(a);
  For i:=Low(a) to High(a) do Memo1.Lines.Add(a[i]);
end;
 


Wie kann man das Array in der Procedure vergrößern?

Übrigens, wenn ich nicht die Referenz übergebe, also das VAR weg lasse, dann bleibt a[2]='Otto'.

Viele Grüße

Willi4Willi
Zuletzt geändert von willi4willi am So 2. Jun 2013, 16:54, insgesamt 1-mal geändert.
 

Viele Grüße

Willi4Willi

------------

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Dynamisches Array von Prozedur übergeben

Beitrag von mschnell »

es muss natürlich

arrS[5]:='Erich'; :D

heißen.

Aber das Verhalten ist trotzdem ziemlich merkwürdig (ich habs übrigens mit Turbo-Delphi getestet, es ist in Lazarus/FPC also sicherlich kein Bug sondern ein Feature.)

Folgendes lässt sich übersetzen:

Code: Alles auswählen

type
  stringArray = array of String;
 
procedure Ausgelagert_1( {var} arrS: stringArray);
begin
  arrS[2]:='Fritz';   // das geht noch
  setlength(arrS,6);  // hier Error: Type mismatch
  arrS[5]:='Erich';
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var  a, r : StringArray;
     i : integer;
begin
  setlength(a,5);
  a[0]:='Otto';
  a[1]:='Otto';
  a[2]:='Otto';
  a[3]:='Otto';
  a[4]:='Otto';
  Ausgelagert_1(a);
  For i:=Low(a) to High(a) do Memo1.Lines.Add(a[i]);
end;
 
- Warum mit der Typ-Definition nun setlength() im Unterprogramm geht, ist mir schleierhaft.

- Ohne "var" wird Fritz nun in das im Hauptprogramm erstellte Array eingetragen . (Keine Ahnung warum es vorher einen Einfluss hatte.)

- Die veränderte Array-Länge wird nur mit var zurück-gegeben. (Scheint mir nicht sehr konsistent damit, dass der Inhalt auch ohne var verändert wird).

-Michael

Benutzeravatar
willi4willi
Lazarusforum e. V.
Beiträge: 167
Registriert: Sa 1. Nov 2008, 18:06
OS, Lazarus, FPC: Windows, Linux (debian) / Lazarus 3.2 / FPC 3.2.2
CPU-Target: i386, win64, arm

Re: Dynamisches Array von Prozedur übergeben

Beitrag von willi4willi »

Hallo!

Ja, das ist schon ein merkwürdiges Verhalten.

Fazit für mich:
  • Typ Array of ... außerhalb definieren, und diesen verwenden

    Code: Alles auswählen

    type
      stringArray = array of String;  
  • Variablenübergabe mit Referenz - ist o.k.

    Code: Alles auswählen

    procedure Ausgelagert_1(var arrS: stringArray);
    begin
      arrS[2]:='Fritz';
      setlength(arrS,6);
      arrS[5]:='Erich';
    end; 
  • Variablenübergabe mit Wert - Vorsicht, nie den Inhalt der übergebenden Variable ändern

    Code: Alles auswählen

    procedure Ausgelagert_2(arrS: stringArray);
    var arrS_neu : StringArray;
    begin
      arrS_neu:=copy(arrS,1,length(arrS));
      arrS_neu[2]:='Fritz';
      setlength(arrS_neu,6);
      arrS_neu[5]:='Erich';
    end;
Frage an din_iso: War das auch Dein Problem?

Viel Grüße

Willi4Willi
 

Viele Grüße

Willi4Willi

------------

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Dynamisches Array von Prozedur übergeben

Beitrag von mschnell »

willi4willi hat geschrieben: Ja, das ist schon ein merkwürdiges Verhalten.
...
[*]Variablenübergabe mit Wert - Vorsicht, nie den Inhalt der übergebenden Variable ändern
Ich hatte (mit Delphi) sogar einmal ein noch abstruseres Verhalten:

Wenn man eine Funktion macht, die als Resultat ein dynamisches Array (eines vorher definierten Typs) zurückgibt und diese Funktion Aufruft, indem man im Hauptprogramm das Resultat auf eine solche Variable zuordnet, kann man in der automatische Variable "Result" im Unterprogramm die vorher definierten Werte der im Hauptprogramm zuzuordnenden Variable auslesen.

Queer !

-Michael
Zuletzt geändert von mschnell am Mo 3. Jun 2013, 16:29, insgesamt 1-mal geändert.

din_iso
Beiträge: 10
Registriert: Sa 11. Mai 2013, 14:09

Re: Dynamisches Array von Prozedur übergeben

Beitrag von din_iso »

willi4willi hat geschrieben:Hallo!

Ja, das ist schon ein merkwürdiges Verhalten.

Fazit für mich:
  • Typ Array of ... außerhalb definieren, und diesen verwenden

    Code: Alles auswählen

    type
      stringArray = array of String;  
  • Variablenübergabe mit Referenz - ist o.k.

    Code: Alles auswählen

    procedure Ausgelagert_1(var arrS: stringArray);
    begin
      arrS[2]:='Fritz';
      setlength(arrS,6);
      arrS[5]:='Erich';
    end; 
  • Variablenübergabe mit Wert - Vorsicht, nie den Inhalt der übergebenden Variable ändern

    Code: Alles auswählen

    procedure Ausgelagert_2(arrS: stringArray);
    var arrS_neu : StringArray;
    begin
      arrS_neu:=copy(arrS,1,length(arrS));
      arrS_neu[2]:='Fritz';
      setlength(arrS_neu,6);
      arrS_neu[5]:='Erich';
    end;
Frage an din_iso: War das auch Dein Problem?

Viel Grüße

Willi4Willi
Nein,leider nicht. In der Prozedur wird ein Array mit unbestimmter Länge erzeugt, welches dann via prozeduraufruf an das hauptprogramm übergeben wird. Ohne diesen befehl: "//SetLength(arrInt , 500);" erhalte ich "Hat Exception Klasse ausgelöst..."

var i: integer;
NewColumn: TListColumn;
arrInt: stringArray;

....

Ausgelagert_1(arrInt);
....

////SetLength(arrInt , 500); <--- Is ja schwachsinn, ich weiß die Länge von meinem Array nich daswurde in der Unit generiert, die Länge wird erst in der unit bekannt, also muss ich ein Dynamisches Array verarbeiten

while i < high(arrInt) do


--->Bumm

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Dynamisches Array von Prozedur übergeben

Beitrag von mschnell »

din_iso hat geschrieben:////SetLength(arrInt , 500); <--- Is ja schwachsinn, ich weiß die Länge von meinem Array nich
???
Du musst die Länge einfach setzen, bevor Du was in das Array reinschreibst ! Wenn Du im Unterprogramm schreibst, kannst Du auch da die Länge ändern (wenn du einen Typ definiert hast und das Array es als var-Parameter übergeben hast).

-Michael

din_iso
Beiträge: 10
Registriert: Sa 11. Mai 2013, 14:09

Re: Dynamisches Array von Prozedur übergeben

Beitrag von din_iso »

Der Fehler war bei mir wie oben Beschrieben, umihnzuvermeiden ist wie schon geschrieben folgendes nötig:

1. Array unter Type definieren
2. In Prozedur mittels "SetLength(TblTeilug.StrXX , 2);" die Größe definieren
3. Reinschreiben []:='Blubb';

indianer-frank
Beiträge: 134
Registriert: So 30. Nov 2008, 21:53

Re: Dynamisches Array von Prozedur übergeben

Beitrag von indianer-frank »

Ein Großteil der Verwirrung in diesem Beitrag (und ähnlichen) kommt von dem Fehler, anzunehmen, daß in

Code: Alles auswählen

 procedure Ausgelagert_1(var arrS: array of String);  
die Variable arrS ein dynamisches Array ist. Das ist falsch! arrS ist ein Open array parameter (siehe FPC-Referenzmanual Abschnitt 14.4.5), diese können mit const, var und auch ohne Zusatz als Parameter in Funktionen und Prozeduren auftreten - und nur dort! Man kann die Länge auslesen mit High(), Low() ist immer 0. Was man selbstverständlich nicht machen kann, ist die Länge verändern.

Gruß Frank

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Dynamisches Array von Prozedur übergeben

Beitrag von mschnell »

indianer-frank hat geschrieben:procedure Ausgelagert_1(var arrS: array of String); Das ist ein Open array parameter
Juhu, das ist die Erkläriung (habe ich vor Urzeiten mal gewusst und verdrängt).

Aber ganz schön verwirrend, zwei verschiedene Bedeutungen mit derselben Syntax zu beschreiben :evil:

Aber auch die anderen aufgezeigten "Probleme" (z.B. Länge setzen ohne var wird ignoriert, Inhalt ändern nicht) sind etwas verwirrend.

-Michael

Antworten