Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Array eines Records als Parameter übergeben


Delete - Mo 29.12.08 23:59
Titel: Array eines Records als Parameter übergeben
Hallo Delphianer!

Ich bin im Moment dabei eine Unit zu schreiben, die häufig benötigte Prozeduren und Funktionen enthält. Das ist weiter nichts besonderes, allerdings scheitere ich bei der Übergabe von Arrays an diese Unit.

Ich habe irgendwo ein Array wie folgt deklariert

Delphi-Quelltext
1:
2:
3:
4:
5:
type TMyRecord = record  // ein Record
  MyContent: String[255]; // mit beliebigen Inhalt
end;

TMyArray = array of TMyRecord;


Nun soll die Prozedur in meiner Unit auf das Array zugreifen und es verändern können

Delphi-Quelltext
1:
2:
3:
4:
procedure MyProcedure(a:???);
begin
  SetLength(a,length(a)+1);
end;


Und genau da -> ??? liegt das Problem. Ich habe mir etwas zu offenen und untypisierten Parametern durchgelesen, allerdings sehe ich nirgendswo eine Möglichkeit die Prozedur so zu gestalten, dass ich beliebige Arrays eines Records übergeben kann, wie man es z.B. bei SetLength tun kann.

Meine Frage also:
Wie kann man eine so freie Parameter-Übergabe wie bei SetLength realisieren?


Xentar - Di 30.12.08 00:02


Delphi-Quelltext
1:
procedure MyProcedure(var a: TMyArray);                    


Delete - Di 30.12.08 00:08

Ich fürchte du hast mich missverstanden.

Ich möchte jedes beliebige Array eines Records übergeben können.
Wenn ich also in einem anderen Programm mein Record so deklariere

Delphi-Quelltext
1:
2:
3:
4:
5:
type TMySecondRecord = record  // ein anderes Record
  DifferentContent: String[255]; // mit anderem Inhalt
end;

TMySecondArray = array of TMySecondRecord;

soll es trotzdem noch möglich sein TMySecondArray an die Prozedur zu übergeben.

Trotzdem danke für deine schnelle Antwort


Xentar - Di 30.12.08 00:11

Achso, du meinst, eine Procedure, die mit allen weltweit in Delphi geschriebenen Arrays klarkommt?
Öhh.. wüsst ich jetzt nicht, ob / wie das geht.


jaenicke - Di 30.12.08 00:15

Das nennt sich "variant open array parameters". Mehr dazu findest du hier unter "Array of const":
http://rvelthuis.de/articles/articles-openarr.html

Das wird beispielsweise bei Format benutzt.

Beispiel:

Delphi-Quelltext
1:
2:
3:
4:
function test(a: array of const): Integer;
begin
  Result := Length(a);
end;


Delete - Di 30.12.08 00:39

Ah, vielen Dank!
Ich werde es morgen mal ausprobieren :D

[OffTopic]
Hatte der Nussknacker-Wettbewerb 2008 was mit Arrays zu tun?! :P
[/OffTopic]


Delete - Di 30.12.08 15:45

Also das mit den "variant open array parameters" funktioniert, allerdings mit einer Einschränkung bei SetLength. Hier mein Code zum speichern und laden eines Arrays:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure SaveArrayToFile(const FileName: String; a: array of const; TypeSize: Integer);
  var f: TFileStream;
      i: integer;
begin
  f := TFileStream.Create(FileName,fmCreate);
  for i := 0 to high(a) do
    f.write(a[i],TypeSize);
  f.free;
end;

procedure LoadArrayFromFile(const FileName: String; a: array of const; TypeSize: Integer);
  var f: TFileStream;
      i: integer;
begin
  f := TFileStream.Create(FileName,fmOpenRead);
  SetLength(a,f.Size div TypeSize);
  for i:= 0 to High(a) do
    f.read(a[i],TypeSize);
  f.free;
end;


SaveArrayToFile funktioniert, aber bei LoadArrayFromFile gibt es für SetLength Inkompatible Typen als Compiler-Fehler. Eigentlich ist das auch nicht verwunderlich, denn SetLength ist ja wie folgt überladen deklariert:

Delphi-Quelltext
1:
2:
procedure SetLength ( var StringToChange  : string; NewLength  : Integer ) ;
procedure SetLength ( var ArrayToChange : Array type; Dim1Length : Integer {;Dim2Length : Integer; ...} ) ;

Die erste Deklaration verstehe ich noch, aber ich weiß nicht was es mit der zweiten auf sich hat, insbesondere bei "var ArrayToChange : Array type;". Ist es denn überhaupt möglich SetLength bei Array of const zu verwenden?


jaenicke - Di 30.12.08 16:34

Nein, das geht nicht, das steht aber auch in dem Link. Dort gibt es auch ein Beispiel mit TConstArray, was dann wohl eher das ist, was du braucht.

Intern ist ein array of const (wie dort ja auch steht) ja ein Array of TVarRec.

Wobei ein solches Vorgehen beim Speichern und Laden schon etwas seltsam ist, ich weiß nicht ob das (sinnvoll) klappt. :nixweiss:

// EDIT:
Eine Idee wäre, dass du dir ähnlich wie bei API Funktionen mit einem leeren übergebenen Array zuerst die Länge geben lässt, diese setzt, und dann erneut die Prozedur aufrufst. (Ich bin mir aber nicht so sicher, ob read und write überhaupt so funktionieren.)


Delete - Di 30.12.08 17:06

Also ich denke dann ist mein Ansatz schon zum scheitern verurteilt und auch nicht ratsam, aber das Beispiel mit TVarRec werde ich mir jetzt mal anschauen, ich hatte es mit gar nicht mehr durchgelesen, weil ich so auf array of const fixiert war, sorry deswegen.

Aber die Frage ist ja mit array of const beantwortet und ich will nun auch nicht ein neues Thema in diesem Thread anfangen.

Also vielen Dank euch beiden, vielleicht eröffne ich demnächst nochmal ein Thema über praxistaugliche Speichermethoden. :wink: