Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Array als Referenz einer Methode übergeben (https://www.delphipraxis.net/143739-array-als-referenz-einer-methode-uebergeben.html)

TheMiller 22. Nov 2009 10:54


Array als Referenz einer Methode übergeben
 
Hallo,

ich habe hier zwei Methoden in einer eigenen "Bibliotheks-Unit" (eigene Zusammenstellung nützlichen Methoden), die mir Schreibarbeit ersparen sollen.

Ich möchte in der Programm-Unit ein dynamisches Array erstellen und dann die Prozedur "AddSQLFields" aus besagter Bib-Unit aufrufen. Dieser soll das zuvor erstellte Array erweitern und die übergebenen Werte eintragen. Wenn alle Werte eingetrage sind, soll eine andere Funktion das Array durchgehen und eine SQL-Query basteln.

Nun möchte ich kein globales Array anlegen. Ich würde gerne das Array als Pointer den Methoden übergeben, sodass diese direkt auf das Array zugreifen.

Nun ist ja ein Array schon ein Pointer. Könnt ihr mir Tipps geben, bitte?

Vielen Dank im Voraus

jfheins 22. Nov 2009 10:57

Re: Array als Referenz einer Methode übergeben
 
Du könntest ein
Delphi-Quellcode:
procedure bla(a:array of const)
übergeben - dann solltest du aber nicht das array an sich ändern (sondern nur die elemente)

TheMiller 22. Nov 2009 10:59

Re: Array als Referenz einer Methode übergeben
 
Hm das wäre nicht so toll. Diese Prozedur, an die das Array übergeben wird, erweitert nämlich das Array.

jfheins 22. Nov 2009 11:01

Re: Array als Referenz einer Methode übergeben
 
Hmmm ... dann kannte mal probieren ob das hier geht:
Delphi-Quellcode:
procedure bla(var a:array of const)
wäre zumindest logisch, aber ob das compiliert ... keine Ahnung ^^

TheMiller 22. Nov 2009 11:03

Re: Array als Referenz einer Methode übergeben
 
Probiere ich gleich mal aus. Kann man aber nicht das ganze mit "^" und "@" lösen?

EDIT: Kompiliert nicht. Inkompatible Typen

TheMiller 22. Nov 2009 12:44

Re: Array als Referenz einer Methode übergeben
 
Hm... bis jetzt habe ich noch keine Lösung, aber eine weitere Idee, die ich allerdings für sehr unschön halte. Deshalb wollte ich fragen, was ihr davon haltet:

Und zwar könnte ich doch von der Methode, die Daten ins Array hinzufügt, mir das neue Array zurückgeben lassen. Das Problem ist ja, dass in der Funktion nicht das Array aus der Haupt-Unit verwendet wird, sondern ein neues erstellt wird. Wenn ich mir das zurückgeben lasse, könnte ich durch "hin-und-her-schieben" von Arrays die Werte addieren.

Wie gesagt, es ist sehr unschön, aber mir fällt keine andere Lösung ein.. Oder könnt ihr mich davon durch andere Lösungen abhalten?

taaktaak 22. Nov 2009 13:08

Re: Array als Referenz einer Methode übergeben
 
Verstehe ich das richtig?
Meinst du so etwas...

Delphi-Quellcode:
type tNumArray = Array of Byte;

var NumArray : tNumArray;

procedure AddNumbers(var a:tNumArray);
begin
  SetLength(a,High(a)+3); // add 2 numbers
  a[High(a)-1]:=44;
  a[high(a) ]:=55;
end;

procedure TfoTest03.FormShow(Sender:TObject);
var i : Integer;
begin
  SetLength(NumArray,Listbox1.Items.Count);

  for i:=0 to Listbox1.Items.Count-1 do       // array aus listbox1
   NumArray[i]:=StrToInt(Listbox1.Items[i]);  // füllen

  AddNumbers(NumArray);                       // array erweitern

  for i:=0 to high(NumArray) do               // array in listbox2
   Listbox2.Items.Add(IntToStr(NumArray[i]))  // anzeigen
end;

TheMiller 22. Nov 2009 13:20

Re: Array als Referenz einer Methode übergeben
 
Ja, genau so, nur ohne globalem Array.

Ich möchte durch verschiedene Methoden auf ein Array zugreifen, welches ich vorher übergebe - eben um die globalen Arrays zu vermeiden.

DeddyH 22. Nov 2009 13:24

Re: Array als Referenz einer Methode übergeben
 
Bei Ralphs Methode kannst Du aber das Array auch in FormShow lokal deklarieren.

TheMiller 22. Nov 2009 13:26

Re: Array als Referenz einer Methode übergeben
 
Stehe ich gerade auf dem Schlauch? Ist der Vorschlag von Ralph genau das, was ich wollte? Ich kann's grad nicht testen...

DeddyH 22. Nov 2009 13:31

Re: Array als Referenz einer Methode übergeben
 
Genau. Wenn Du wieder testen kannst, versuch es mal damit (klitzekleine Änderung):
Delphi-Quellcode:
type tNumArray = Array of Byte;

procedure AddNumbers(var a:tNumArray);
begin
  SetLength(a,High(a)+3); // add 2 numbers
  a[High(a)-1]:=44;
  a[high(a) ]:=55;
end;

procedure TfoTest03.FormShow(Sender:TObject);
var i : Integer;
    NumArray : tNumArray; //nun als lokale Variable
begin
  SetLength(NumArray,Listbox1.Items.Count);

  for i:=0 to Listbox1.Items.Count-1 do       // array aus listbox1
   NumArray[i]:=StrToInt(Listbox1.Items[i]);  // füllen

  AddNumbers(NumArray);                       // array erweitern

  for i:=0 to high(NumArray) do               // array in listbox2
   Listbox2.Items.Add(IntToStr(NumArray[i]))  // anzeigen
end;

TheMiller 22. Nov 2009 13:34

Re: Array als Referenz einer Methode übergeben
 
Danke. Das wird in ca. 1-2 Stunden sein. Gebe auf jeden Fall Rückmeldung. Danke!

TheMiller 22. Nov 2009 17:24

Re: Array als Referenz einer Methode übergeben
 
Also, genau so, wie es jetzt von dir gepostet wurde (DeddyH), hatte ich es von Anfang an gehabt. Hier nochmal meine Version, falls ich was übersehen habe.

Delphi-Quellcode:
type
  TSQLData = array of array of String;

type
  //SQL-Funktionen
  procedure AddSQLField(data: TSQLData; feld: String; wert: String; utf8enc: Boolean = true);
  function InsertSQL(ZQuery: TZQuery; table: String; data: TSQLData): Boolean;

//SQL-Funktionen
procedure AddSQLField(data: TSQLData; feld: String; wert: String; utf8enc: Boolean = true);
begin
  SetLength(data, Succ(Length(data)), 2);
  if (utf8enc) then
  begin
    data[High(data)][0]:=utf8encode(feld);
    data[High(data)][1]:=utf8encode(wert);
  end else
  begin
    data[High(data)][0]:=feld;
    data[High(data)][1]:=wert;
  end;
end;

function InsertSQL(ZQuery: TZQuery; table: String; data: TSQLData): Boolean;
var
  i: Integer;
begin
  for i:=0 to High(data) do
  begin
    ShowMessage(data[i][0]+' '+data[i][1]);
  end;
end;

///////////////////
//// HAUPTUNIT ////
///////////////////

procedure TForm1.frmSchemabtnSaveClick(Sender: TObject);
var
  daten: TSQLData;
begin
  AddSQLField(daten, 'pid', '1');
  AddSQLField(daten, 'titel', frmGesetz.Editor.Text);
  AddSQLField(daten, 'text', 'test2');
  InsertSQL(ZQuery1, 'test', daten);
end;
So, und in der Bibliotheks-Unit wird nicht die lokale Variable "Daten" genutzt, sondern eine völlig neue, gleichen Typs initialisiert und beschrieben.

Ich verstehe aber ehrlich gesagt nicht, wieso das so ist. Denn, ein Array ist doch schon ein Pointer auf eine Adresse und wenn ich diesen übergebe, wie kann dann ein neues Array angelegt werden?

Danke!

DeddyH 22. Nov 2009 17:30

Re: Array als Referenz einer Methode übergeben
 
Bei Arrays verhält es sich anders als bei Objekten. Übergib die Arrays doch einmal als Var-Parameter, dann sollte das auch klappen.

Apollonius 22. Nov 2009 17:31

Re: Array als Referenz einer Methode übergeben
 
Du hast Detlefs "var" unterschlagen. Der Grund, warum dies nötig ist, ist einfach: Es kann vorkommen, dass SetLength die Array-Daten verschieben muss, der Zeiger selbst wird also verändert. Aus diesem Grund ist der erste Parameter von SetLength auch als var deklariert. Wenn du nun den Array-Parameter nicht als var deklarierst, zählt der Parameter als neue Referenz (dynamische Arrays unterliegen der Referenzzählung). SetLength muss daher in jedem Fall ein neues Array anlegen, um die andere Referenz nicht zu verändern.

TheMiller 22. Nov 2009 17:46

Re: Array als Referenz einer Methode übergeben
 
Oha... das wusste ich nicht. Auch ist mir das VAR garnicht aufgefallen. Ich sollte öfter 9Live schauen, um meine Augen zu trainieren ;)

Ich werde das - leider wieder - erst später testen ...

Vielen Dank

sx2008 22. Nov 2009 18:43

Re: Array als Referenz einer Methode übergeben
 
Warum muss es denn ein Array sein?
Ein Liste (z.B. eine Ableitung von TList oder TObjectlist) kann all das leisten, was du brauchst.

Übrigens, schau die mal folgende Deklarationen an:
Delphi-Quellcode:
procedure AddSQLField(data: TSQLData; feld: String; wert: String; utf8enc: Boolean = true);
function InsertSQL(ZQuery: TZQuery; table: String; data: TSQLData): Boolean;
Was fällt auf? Richtig, beides Mal wird TSQLData übergeben.
Eigentlich müsste doch TSQLData eine Klasse sein, dann würde sich Einiges vereinfachen.

TheMiller 22. Nov 2009 21:08

Re: Array als Referenz einer Methode übergeben
 
Oh jubel, oh freu... ;)

Funktioniert richtig gut. Es lag tatsächlich am --var--. Vielen Dank.

@sx2008: Ich mag arrays... ;) Nein, ich wollte keine Klasse bauen, weil mir dafür der Aufwand zu groß und das Projekt in dem Punkt zu klein ist. Außerdem kann ich auf Grund einer Bandscheiben-OP nicht sitzen. Darf nur stehen. Das ist auch der Grund, warum ich nie so lange am PC sein kann. Nunja, all diese Sachen summieren sich dann dazu, dass ich mich zu dieser Lösung entscheide, die ja eigentlich so auch nicht schlecht ist, oder?

sx2008 23. Nov 2009 04:15

Re: Array als Referenz einer Methode übergeben
 
Zitat:

Zitat von DJ-SPM
@sx2008: Ich mag arrays... ;)

Deine Fixierung auf einfache Datentypen nennt man übrigens "Bei Google suchenPrimitive Obsession" :-)
Bei Konstruktionen wie array of array of TDatentyp muss man jeder Stelle die Indexgrenzen beachten.
Durch eine Klasse wird dies wesentlich vereinfacht und sicherer.
Ansonsten gute Besserung. :hi:

TheMiller 23. Nov 2009 08:50

Re: Array als Referenz einer Methode übergeben
 
;)

Danke


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:55 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