AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

SetLength mein problem

Ein Thema von EWeiss · begonnen am 31. Okt 2006 · letzter Beitrag vom 1. Nov 2006
Antwort Antwort
Seite 1 von 2  1 2      
EWeiss
(Gast)

n/a Beiträge
 
#1

SetLength mein problem

  Alt 31. Okt 2006, 02:10
Hi

Wer kann mir mal richtig das verschieben Dimensionieren von Arrays in Delphi beibringen.
Irgendwie komme ich mit der Materie nicht zurecht und gute Tutorials gibt es auch nicht.

Ich möchte also lernen wie man mit arrays unter Delphi richtig umgeht.

Würde mich über ein paar Beispiel mit genauer Beschreibung freuen.
Nix copy/paste das bringt mir nichts.

Also von Anfang an!
Was mich zuerst Interessiert wären Dynamische Arrays in verbindung mit Records.

Dimensionieren
Redimensionieren

New(.. in verbindung mit Arrays
ReAllocMem
GetMem
Copy

usw ...

Halt die ganze palette welche ein vernünfiges(Stabiles) arbeiten mit arrays ermöglicht.

Gruß
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: SetLength mein problem

  Alt 31. Okt 2006, 02:48
Erstmal für den Unterschied statische / dynamische Arrays:
Delphi-Quellcode:
Type
  StaticArray = Array[0..2] Of RecordType;

  DynamicArray = Array Of RecordType;
Ein dynamisches Array dimensionierst und realloziierst du einfach nur mit SetLength() und der neuen Länge. Da ist nix mit ReAllocMem oder ähnlichem.

Mit den Funktionen Low() und High() bekommt man den untersten und oberen Index des Arrays raus - funktioniert mit dynamischen wie auch statischen Arrays. Durch den letzten Fakt ist Code welcher auf diesen Funktionen baut (und nicht fest von einem Index 0 ausgeht) auch immer leicht auf ein statisches Array umstellbar.

Length() ermittelt die Anzahl der Elemente in einem Array (statisch wie auch dynamisch). Beachte hierbei den Unterschied zwischen Index und Anzahl der Elemente. Auch Length() ist auf beide Typen von Arrays anwendbar.

Noch ein Hinweis zum Schluss: Wenn man ein statisches Array an eine Funktion übergibt, welche ein dynamisches Array als Parameter hat, dann wird das statische auf den Index 0 angepasst. Folgendes Beispiel:

Delphi-Quellcode:
Type
  MyArray = Array[5..10] Of Integer;

Procedure MySubFunc(Const A: Array Of Integer);
Begin
    // ergibt von 0 bis 5
  WriteLn('MySubFunc(): Array from ', Low(A),' to ', High(A));
End;

Procedure CallIt;
Var
  lArr : MyArray;
Begin
    // ergibt 5 bis 10
  WriteLn('CallIt(): Array from ', Low(lArr),' to ', High(lArr));

  MySubFunc(lArr);
End;
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

Re: SetLength mein problem

  Alt 31. Okt 2006, 03:54
Erst mal danke für die ausfühliche Beschreibung.
Zitat:
Erstmal für den Unterschied statische / dynamische Arrays:
Habe ich soweit verstanden.
Was mir auffällt der wechsel vom Statisch zum dynamischen array in einer Function
kommt ja einen 2 Dimensionalen array gleich oder sehe ich das verkehrt?

Array [0..5, 5..10]. Oder?
Könnte man ja dann auch direkt so auslegen. Oder macht das einen unterschied.

Ein Beispiel: Neue Frage.

Delphi-Quellcode:
Type
 PWindowDescr = ^TWindowDescr;
 TWindowDescr = Packed record
    hWnd : DWORD;
    ProcessID : Pointer;
    Title : String;
    Klass : String;
    ExeName : String;
End;

Var
DynamicArray : array of PWindowDescr;
Was ich nun nicht verstehe ist folgendes!
Wenn ich nun ein DynamicArray in einer Function einsetze ..

Function GetWindowList(DynamicArray : array of PWindowDescr): DWORD; Warum kann ich dann nicht einfach bei SetLength ..
SetLength(DynamicArray, 100) eingeben ?

Theoretisch müßte doch dann das Array um 100 einträge Redimensioniert werden.

Woran liegt es nun das es auf diese weise nicht geht.
Der Fehler welcher angezeigt wird ist 'incompatible types' Es ist aber doch ein dynamisches Array.

Ich habe festgestellt das dies nur geht wenn man eine extra Type declariert
DynamicArray2 = array of PWindowDescr; und dann mit SetLength(DynamicArray2, 100) eine neue größe zuweist.
Warum geht es also nur auf dieser art

Ich möchte ja die Länge von DynamicArray ändern und nicht die von DynamicArray2
Das sind so die kleinen Probleme wo ich nicht so recht bescheid weis.

Gruß
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#4

Re: SetLength mein problem

  Alt 31. Okt 2006, 10:32
Hallo,
Zitat von EWeiss:
Was mir auffällt der wechsel vom Statisch zum dynamischen array in einer Function
kommt ja einen 2 Dimensionalen array gleich oder sehe ich das verkehrt?
Ja, das siehst Du verkehrt.
im obigen Beispiel wird das statische Array in der Funktion so behandelt, als wäre es ein dynamisches. Der Aufbau der beiden Typen ist ja grundsätzlich der selbe.
Zitat von EWeiss:
Ein Beispiel: Neue Frage.
...
Was ich nun nicht verstehe ist folgendes!
Wenn ich nun ein DynamicArray in einer Function einsetze ..

Function GetWindowList(DynamicArray : array of PWindowDescr): DWORD; Warum kann ich dann nicht einfach bei SetLength ..
SetLength(DynamicArray, 100) eingeben ?
Um so etwas zu machen, musst Du Dir, wie Du ja schon festgestellt hast, einen eigenen Array-Typen deklarieren.
Zitat von EWeiss:
Ich möchte ja die Länge von DynamicArray ändern und nicht die von DynamicArray2
Das sind so die kleinen Probleme wo ich nicht so recht bescheid weis.
Es gibt ja für Dich keinen Unterschied zwischen den beiden Array-Deklarationen, nur für den Compiler. Im Grunde ist es ganz einfach: Du deklarierst einen neuen Variablentypen und verwendest diesen überall. Du musst nämlich wissen:
Wenn Du irgendwo ein "array of Irgenwas" übergibst, ist das immer ein eigener Typ und gänzlich unterschiedlich zu einem anderen "array of irgendwas". Also;
Delphi-Quellcode:
function X(Value: array of Integer): Boolean;
begin
  // Tu was
end;

function Y(Value: array of Integer): Boolean;
begin
  // Tu was
end;
Beide Funktionen verwenden den gleichen Array-Aufbau, aber der Typ (und damit die Signatur der Funktion) ist immer einzigartig. Delphi erschafft quasi implizit einen neuen Typen.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#5

Re: SetLength mein problem

  Alt 31. Okt 2006, 11:20
Zitat von EWeiss:
Was mich zuerst Interessiert wären Dynamische Arrays in verbindung mit Records.

Dimensionieren
Redimensionieren

New(.. in verbindung mit Arrays
ReAllocMem
GetMem
Copy
Arrays sind imho noch ein "etwas" veraltetes Gestrick, um Datenstrukturen im Speicher zu halten, aus Kompatibilitätsgründen zum guten alten Pascal. Delphi bietet aber andere, objektorientierte, Gebilde an, um Analoges wesentlich eleganter zu lösen. Am einfachsten sind da wohl die TObjectList. Diese Liste erlaubt es die, beliebig viele, sogar unterschiedliche, Objekte in eine Liste aufzunehmen. Diese Liste entspricht dann deinem Array, und jedes einzelne Objekt wäre ein Record. Es verhält sich also fast alles wie bei den Arrays, nur mit einigen wichtigen, funktionellen Erweiterungen. Beim Löschen eines Objektes aus der Liste musst Du nix neu reallokieren indem du die hinteren Arraywerte eins nach vorne verschiebst. Auch um die Speicherfreigabe musst Du dich nicht kümmern. Ein TObjectList.Free gibt den Speicher jedes einzelnen Objektes gleich mit frei.

Ist sicherlich ne Überlegung wert, sich damit zu befassen.
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#6

Re: SetLength mein problem

  Alt 31. Okt 2006, 11:27
Hallo,
Zitat von Jelly:
Arrays sind imho noch ein "etwas" veraltetes Gestrick, um Datenstrukturen im Speicher zu halten, aus Kompatibilitätsgründen zum guten alten Pascal.
Das ist nur die halbe Wahrheit. Gerade an der obigen Deklaration sieht man, dass Arrays das einzige Mittel sind, um mit dem Windows-API bzw. native zwischen verschiedenen Programmen zu kommunizieren. Durch das unterschiedliche Objektmodell funktioniert eine ObjectList da leider nicht, auch wenn das schön wäre.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#7

Re: SetLength mein problem

  Alt 31. Okt 2006, 11:29
Zitat von xaromz:
Das ist nur die halbe Wahrheit. Gerade an der obigen Deklaration sieht man, dass Arrays das einzige Mittel sind, um mit dem Windows-API bzw. native zwischen verschiedenen Programmen zu kommunizieren. Durch das unterschiedliche Objektmodell funktioniert eine ObjectList da leider nicht, auch wenn das schön wäre.
Dem ist natürlich zu berücksichtigen, ganz klar.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

Re: SetLength mein problem

  Alt 31. Okt 2006, 17:38
Zitat:
Es gibt ja für Dich keinen Unterschied zwischen den beiden Array-Deklarationen, nur für den Compiler. Im Grunde ist es ganz einfach: Du deklarierst einen neuen Variablentypen und verwendest diesen überall. Du musst nämlich wissen:
Wenn Du irgendwo ein "array of Irgenwas" übergibst, ist das immer ein eigener Typ und gänzlich unterschiedlich zu einem anderen "array of irgendwas". Also;
Delphi-Quellcode:
function X(Value: array of Integer): Boolean;
begin
  // Tu was
end;

function Y(Value: array of Integer): Boolean;
begin
  // Tu was
end;
Beide Funktionen verwenden den gleichen Array-Aufbau, aber der Typ (und damit die Signatur der Funktion) ist immer einzigartig. Delphi erschafft quasi implizit einen neuen Typen.
Danke.
Ich hoffe das jetzt richtig verstanden zu haben.

Hier die änderung.

Delphi-Quellcode:
 PWindowDescr = ^TWindowDescr;
 TWindowDescr = record
    hWnd : HWND;
    ProcessID : Pointer;
    Title : String;
    Klass : String;
    ExeName : String;
End;
    AWindowDescr = array of PWindowDescr;

Var
    wDescr : AWindowDescr;

// Alle offene Fenster suchen.
Function GetWindowList(var wDescr: AWindowDescr): DWORD;
Var
  IntI : Integer; // Zähler füt die Fenster Handle
  h_wnd : HWND; // Fenster Handle
  Index : Integer;
Begin
    // Zähler initialisieren
    IntI := 0;
    h_wnd := GetTopWindow(0);
    // Zuweisen von 100 Array Elementen of PWindowDescr
    // Zum einlesen der Fenster Handle
    Index := 100;
    SetLength(wDescr, Succ(index));
    New(wDescr[index]);
    ZeroMemory(wDescr[index], SizeOf(wDescr[index]^));

    Repeat
      // Zähler um 1 erhöhen
      inc(IntI);
      // Wenn mehr als High Fenster Handle gefunden
      If IntI > High(wDescr) Then
        // Array um 10 erhöhen
        SetLength(wDescr, High(wDescr) + 10);

        // Fenster Handle ermitteln
        h_wnd := GetWindow(h_wnd, GW_HWNDNEXT);
        // Fenster Handle gefunden
        If h_wnd <> 0 Then
         begin
           New(wDescr[IntI]);
           ZeroMemory(wDescr[IntI], SizeOf(wDescr[IntI]^));
           // Wert zuweisen
           wDescr[IntI].hWnd := h_wnd;
           // Window Informationen einlesen
           GetWindowInfo(wDescr[IntI]);
         end;

    // Schleife durchlaufen bis kein Fenster Handle mehr existiert
    until h_wnd = 0;

    // Array Redimensionieren Fenster-Handle Count
    SetLength(wDescr, IntI);
    // Ergebnis übergeben
    Result := IntI;

End;
Es läuft alles einträge werden richtig eingelesen und zugewiesen.
Wäre nicht schlecht wenn mir jemand fehler meldet wenn ersichtlich !

Gruß
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

Re: SetLength mein problem

  Alt 31. Okt 2006, 17:40
Zitat:
Ist sicherlich ne Überlegung wert, sich damit zu befassen.
Danke aber das geht am Thema vorbei es ging mir um den Befehl SetLength

gruß
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#10

Re: SetLength mein problem

  Alt 31. Okt 2006, 19:51
Ich gebe deinen Quellcode mal wieder mit ein paar Anmerkungen als Kommentar

Delphi-Quellcode:
 PWindowDescr = ^TWindowDescr;
 TWindowDescr = record
    hWnd : HWND;
    ProcessID : Pointer;
    Title : String;
    Klass : String;
    ExeName : String;
End;
    AWindowDescr = array of PWindowDescr; // Warum ein Array von Zeigern auf den Record anstatt eines Arrays of Records?

Var
    wDescr : AWindowDescr;

// Alle offene Fenster suchen.
Function GetWindowList(var wDescr: AWindowDescr): DWORD;
Var
  IntI : Integer; // Zähler füt die Fenster Handle
  h_wnd : HWND; // Fenster Handle
  Index : Integer;
Begin
    // Zähler initialisieren
    IntI := 0;
    h_wnd := GetTopWindow(0);
    // Zuweisen von 100 Array Elementen of PWindowDescr
    // Zum einlesen der Fenster Handle
    Index := 100;
    SetLength(wDescr, Succ(index)); // also werden hier 101 Elemente angelegt, Zugreifbar mit Index 0 bis 100

    New(wDescr[index]); // warum holst du dir den Speicher für nur einen Record (den an Index 100)? Was ist der Sinn?

    ZeroMemory(wDescr[index], SizeOf(wDescr[index]^)); // warum initialisierst du den Record bei Index 100?
                                                        // Ich glaube der erste Parameter müsste noch ein ^ bekommen, weil sonst
                                                        // schreibt ZeroMemory die Array-Pointer-Liste mit 0'en voll anstatt des Records
    Repeat
      // Zähler um 1 erhöhen // warum? Willst du Index 0 nicht nutzen? Wenn vor dem Until ein Inc(IntI)
      inc(IntI);

      // Wenn mehr als High Fenster Handle gefunden
      If IntI > High(wDescr) Then
        // Array um 10 erhöhen
        SetLength(wDescr, High(wDescr) + 10); // High() gibt dir den höchsten Index an, aber nicht die Anzahl der Elemente. SetLength() will die Anzahl der neuen Elemente, also Anzahl der Elemente bisher + 10, sprich: SetLength(wDescr, Length(wDescr) + 10);

        // Fenster Handle ermitteln
        h_wnd := GetWindow(h_wnd, GW_HWNDNEXT);
        // Fenster Handle gefunden
        If h_wnd <> 0 Then
         begin
           New(wDescr[IntI]); // beachte hier: es ist der Index 100 schon initialisiert!
           ZeroMemory(wDescr[IntI], SizeOf(wDescr[IntI]^)); // siehe oben: 1. Parameter sollte noch ein ^ bekommen
           // Wert zuweisen
           wDescr[IntI].hWnd := h_wnd;
           // Window Informationen einlesen
           GetWindowInfo(wDescr[IntI]);
         end;

    // Schleife durchlaufen bis kein Fenster Handle mehr existiert
    until h_wnd = 0;

    // Array Redimensionieren Fenster-Handle Count
    SetLength(wDescr, IntI); // wenn du oben das mit dem Inc(IntI) änderst, dann hier Succ(IntI) als höchstes Element setzen
    // Ergebnis übergeben
    Result := IntI;

End;
Ich hoffe das hilft und löst nicht wieder Beleidigungen aus...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:11 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