Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Listen und wie man sie nutzt (https://www.delphipraxis.net/152461-listen-und-wie-man-sie-nutzt.html)

Obelisk2k5 23. Jun 2010 15:28

Listen und wie man sie nutzt
 
Nachdem ich hier schonmal gute Hilfe zum Thema Datenverwaltung erhalten habe,
gehe ich gleich zu meinem nächsten Problem über, bei dem ich Hilfestellung bräuchte:

Ich habe ein Programm geschrieben, dass zur Laufzeit Records in einem Array speichert und damit arbeitet.

Nun möchte ich dieses Array durch Listen ersetzen.

Ich habe schon einen Ansatz parat, nur weiß ich nicht, ob das so richtig ist und was geändert werden muss.
Daher schreibe ich den relevanten Programmcode hier auf und stelle programmbezogene Fragen als Kommentare im Code.

Zunächst einmal das Record TDeveloper samt Komponenten,
welches nicht verändert werden sollte.
Es ist in eine andere Unit ausgelagert:

Delphi-Quellcode:
TName = String[20];

TPerson = record
  sureName : TName;
  lastName : TName;
end;

TDeveloperID = Integer;

TDeveloper = record
  developerID : TDeveloperID;
  developerPerson : TPerson;
  developerDescription : TDescription;
end;
Nun der interessante Teil:
Delphi-Quellcode:
type
  TListe = ^TElement;
  TElement = record
               content : TDeveloper;
               Next : TListe;
             end;

// Ist dies so richtig? Habe mich etwas eingelesen, und da wurde ein Record mit einem Next-Teil
// benutzt. Da ich das eigentliche Record nicht verändern will, habe ich es so gelöst.
var
  First : TListe = nil;
  Last : TListe = nil;
  Allocations : integer;
// Wird benutzt, um im Finalizationteil zu prüfen, ob alle Listenelemente wieder freigegeben wurden


function NewElement(person: TPerson; description: TDescription) : boolean;
var
  TempElement,
  RunPointer : TListe;
  I: byte;
  Temp_ID: Integer;
begin
  if developersCount < DEVELOPER_MAX then
  begin
    First := nil;

// ---- Temporäre ID -----------------------------------------------------------

    Temp_ID := DEVELOPER_ID_MIN + DEVELOPER_MIN;

// ---- Wenn es schon andere Developer gibt, wird die Temporäre ID inkrementiert,
// ---- bis sie einen Wert hat, der noch nicht als Developer ID vergeben ist ---

  if developersCount > 0 then
    begin
    for I := DEVELOPER_MIN to DEVELOPER_MAX do
    Runpointer := first;
      While RunPointer <> nil do
        begin
        if Runpointer^.content.developerID = Temp_ID then
          inc(Temp_ID);
          Runpointer := Runpointer^.Next;
        end;
    end;
//--------------------------------------------------------------------------------

    new (TempElement);
    TempElement.content.developerID := Temp_ID;
    TempElement.content.developerPerson := person;
    TempElement.content.developerDescription := description;
    TempElement.Next := nil;
    if first = nil then
    begin
      First := TempElement;
      Last := First;
    end
      else
      begin
        Last^.Next := TempElement;
        Last := Last^.Next;
      end;
    NewElement := true;
  end
    else NewElement := false;
end;

// Noch etwas: In dem Berspiel, das ich gelesen habe, lieferte die Funktion NewElement einen
// Rückgabewert vom Typ TListe und am Ende wurde NewElement := First; gesetzt.
// Nur brauche ich eine Funktion, die bei Erfolg true liefert.
// Wieso wird NewElement auf First gesetzt und wie löse ich das am besten?

idefix2 23. Jun 2010 15:47

AW: Listen und wie man sie nutzt
 
Es gibt doch in delphi die fertige Klasse TList, die alles beinhaltet, was Du für die Verwaltung von Listen brauchst.

Von der brauchst Du nur mehr Deine spezifische Klasse ableiten.

Obelisk2k5 23. Jun 2010 17:18

AW: Listen und wie man sie nutzt
 
In den Beispielen, die ich gelesen habe, wird TListe so als typ deklariert:

Code:
type
  TListe = ^TElement;
  TElement = record
               Value : Integer;
               Next : TListe;
             end;

var
  First : TListe; {Einstiegszeiger}
Da ich das Endergebnis einreichen muss, werde ich mich wohl daran halten müssen.

Hansa 23. Jun 2010 17:41

AW: Listen und wie man sie nutzt
 
Ist die Fragestellung so vorgegeben ? Es geht mir da um das Hütchen :^. Also wären das dann verkettete Listen etc. Dann geht es mehr um die Theorie. In der Praxis stellt Delphi jedenfalls einiges an fertigen Methoden zur Verfügung. TList, wie bereits gesagt und TObjectList. Und dafür braucht man kein ^. Oder etwa doch ? :mrgreen:

idefix2 23. Jun 2010 18:06

AW: Listen und wie man sie nutzt
 
Es kommt darauf an, was Du willst:

Willst Du üben, wie das Programmieren von Listenstrukturen aussieht, dann wirst Du irgend so eine Pointer Struktur brauchen, mit der Du Listen nachbildest. Das kann je nach Bedarf eine einfach oder doppelt verkettete Liste oder ein B-Baum oder was auch immer sein.

Wenn Du einfach nur eine Liste brauchst, dann verwende TList oder TObjectlist, da hast Du nichts mehr mir "^" zu tun, die ganze Zeigerlogik ist in der Klasse schon fertig und gekapselt. Schau Dir dazu in der Delphi Hilfe die beiden Klassen an.

Obelisk2k5 23. Jun 2010 18:12

AW: Listen und wie man sie nutzt
 
Zitat:

Zitat von idefix2 (Beitrag 1031135)
Es kommt darauf an, was Du willst:

Willst Du üben, wie das Programmieren von Listenstrukturen aussieht, dann wirst Du irgend so eine Pointer Struktur brauchen, mit der Du Listen nachbildest. Das kann je nach Bedarf eine einfach oder doppelt verkettete Liste oder ein B-Baum oder was auch immer sein.

Wenn Du einfach nur eine Liste brauchst, dann verwende TList oder TObjectlist, da hast Du nichts mehr mir "^" zu tun, die ganze Zeigerlogik ist in der Klasse schon fertig und gekapselt. Schau Dir dazu in der Delphi Hilfe die beiden Klassen an.

Ich möchte ersteres, undzwar eine einfach verkettete Liste.

Luckie 23. Jun 2010 18:23

AW: Listen und wie man sie nutzt
 
Dann guck mal hier: http://www.michael-puff.de/Programmi...orials/Listen/

idefix2 23. Jun 2010 18:32

AW: Listen und wie man sie nutzt
 
Dann passt das wahrscheinlich in etwa so, wie Du geschrieben hast. Allerdings dient das System, nach dem Du Deinen Code einrückst, eher der Verwirrung des Gegners (und der eigenen), da fühl ich mich überfordert, dem im Detail nachzugehen:

Delphi-Quellcode:
if developersCount > 0 then
    begin
    for I := DEVELOPER_MIN to DEVELOPER_MAX do
    Runpointer := first;
      While RunPointer <> nil do
        begin
        if Runpointer^.content.developerID = Temp_ID then
          inc(Temp_ID);
          Runpointer := Runpointer^.Next;
        end;
    end;
Irgendwie sollte man glauben, dass da eine Riesen Schleife für I programmiert ist. Tatsächlich wird aber in der Schleife nur runpointer := first immer wieder ausgeführt, danach macht das Programm mit dem While ausserhalb der For Schleife weiter. Ich glaube nicht, dass das sehr sinnvoll ist.

Ein weiterer Hinweis, um lesbaren Code zu erzeugen:

statt

Delphi-Quellcode:
procedure xyz;
begin
if Normalfall then
  begin
  endlose wurst von Code, um eine Stufe eingerückt,
  mit vielen Unterblöcken,
  dass man mühsam zusammenpassende Begin-ends suchen muss
  end
else
  x:=1
end;
ist m.E. ungleich übersichtlicher:

Delphi-Quellcode:
procedure xyz;
begin
if sonderfall then begin x:=1; exit end;

Endlose Wurst von Code nicht in einem Then-Zweig eingerückt, sondern auf der Hauptebene.

end;

Obelisk2k5 23. Jun 2010 19:43

AW: Listen und wie man sie nutzt
 
Zitat:

Zitat von Luckie (Beitrag 1031139)

Danke für den Link.

[Nachfolgendes Problem selbst behoben können]

Zitat:

Zitat von idefix2 (Beitrag 1031143)
Dann passt das wahrscheinlich in etwa so, wie Du geschrieben hast. Allerdings dient das System, nach dem Du Deinen Code einrückst, eher der Verwirrung des Gegners (und der eigenen), da fühl ich mich überfordert, dem im Detail nachzugehen:
[...]

Auch dafür danke.
Ich mache automatisch Einrückungen innerhalb jeder Schleife so wie zwischen allen begin & ends.
Aber anscheinend komme ich damit selbst durch einander und es ist zudem zuviel des Guten.
Werde dann wohl versuchen, mir ein einheitliches Schema mit weniger Einrückungen anzugewöhnen.

Obelisk2k5 23. Jun 2010 21:01

AW: Listen und wie man sie nutzt
 
Ich habe jetzt einen anderen Fehler.

Und zwar bekomme ich die Fehlermeldung
Zitat:

Im Projekt [Name] ist eine Exception der Klasse EAccessViolation mit der Meldung
'Zugriffsverletzung bei Adresse 004C2DDA in Modul '[Name]'.
Lesen von Adresse 00000000 aufgetreten.
Code:
Delphi-Quellcode:
type
  TListe = ^TElement;
  TElement = record
               content : TDeveloper;
               Next : TListe;
             end;

var
  First : TListe = nil;
  Last : TListe = nil;
  Current : TListe;
  Allocations : integer = 0;

function newDeveloper(person: TPerson; description: TDescription) : boolean;
var
  RunPointer : TListe;
  I: byte;
  Temp_ID: Integer;
begin
  if developersCount < DEVELOPER_MAX then
  begin
  // ---- Temporäre ID -------------------------------------------------------
  Temp_ID := DEVELOPER_ID_MIN;
  //- Wenn es schon andere Developer gibt, wird die Temporäre ID inkrementiert,
  //-- bis sie einen Wert hat, der noch nicht als Developer ID vergeben ist --
  if developersCount > 0 then
    begin
    for I := DEVELOPER_MIN to DEVELOPER_MAX do
      begin
      Runpointer := first;
      While RunPointer <> nil do
        begin
        if Runpointer^.content.developerID = Temp_ID then inc(Temp_ID);
        Runpointer := Runpointer^.Next;
        end;
      end;
    end;
  new (Current);
  inc(Allocations);
  Current.content.developerID := Temp_ID;
  Current.content.developerPerson := person;
  Current.content.developerDescription := description;
  Current.Next := nil;
  if last = nil then
    begin
    First := Current;
    Last := Current;
    end
    else
     begin
     Last.Next := Current;
     Last := Current;
     end;
  newDeveloper := true;
  end
  else newDeveloper := false;
end;

function developersCount: Integer;
var
  i : integer;
begin
  i := 0;
  current := first;
  while current <> nil do
    begin
    inc(i);
    current := current^.Next;
    end;
  developersCount := i;
end;

function getDeveloperByIndex(index: Cardinal): TDeveloper;
var
  temp : TDeveloper;
  i: Integer;
begin
  i := 0;
  current := first;
  while i <> index do
  begin
    inc(i);
    current := current^.Next;
  end;
  getDeveloperByIndex := current^.content; // <<====== Hier tritt der Fehler auf.
end;
Ich füge mit NewDeveloper einen developer hinzu.
In einer anderen Unit lasse ich eine for-Schleife von 1 - developersCount durchlaufen,
bei dem ich den developer mit dem Index I durch getDeveloperbyIndex auslesen lasse und
einige Werte in einer listbox anzeigen lasse.

Die obigen Codeteile sind die einzigen, die ich verändert habe (vorher lief alles über Arrays),
von der anderen Unit sollte der Fehler nicht kommen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:35 Uhr.
Seite 1 von 3  1 23      

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