AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Problem mit einer Stringlist und Pointern
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit einer Stringlist und Pointern

Ein Thema von Tormentor32 · begonnen am 11. Jan 2007 · letzter Beitrag vom 12. Jan 2007
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Benutzerbild von Tormentor32
Tormentor32

Registriert seit: 27. Okt 2005
Ort: Düsseldorf
369 Beiträge
 
Delphi XE5 Professional
 
#1

Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 08:00
Hallo DPler!

Ich habe in meinem Programm folgendes vor: Ich will einen Stromkreis darstellen, der auch ineinander verschachtelte Parallel und Reihenschaltungen beimhalten kann, dazu habe ich mir folgendes überlegt:
Delphi-Quellcode:
// Ich habe zunächst meinen Typ TBauteil
type
  TBauteil = Record
    ID,Parent: string; // Jedes Bauteil hat eine eindeutige ID
    Typ: TBauteilTyp;
    Next: Array of PBauteil
  end;
// und einen Pointertyp für TBauteil
  PBauteil = ^TBauteil;
// Und zu guter Letzt noch meine Klasse für das verketten von Bauteilen
  TBauteilListe=class(Tobject)
  private
    FRoot: PBauteil;
    function GetBauteil(ID: string): PBauteil;
    function GetLines: TStringlist;
    procedure NilBauteile;
  public
    constructor Create;
    destructor Destroy; override;
    function AddBauteil(ID: string; Typ: TBauteilTyp; Parent: string): boolean;
    property Items[ID: string]: PBauteil read GetBAuteil;
    property Lines: TStringlist read GetLines;
  end;
Jetzt habe ich ein Prozedur zum einfügen neuer Bauteile
Delphi-Quellcode:
function TBauteilListe.AddBauteil(ID: string; Typ: TBauteilTyp;
  Parent: string): boolean;
var p: PBauteil;
begin
  p := GetBauteil(Parent);
  if p <> nil
    then
      begin
        setlength(p^.Next,length(p^.Next)+1);
        new(p^.Next[high(p^.next)]);
        p^.Next[high(p^.next)]^.ID := ID;
        p^.Next[high(p^.next)]^.Typ := Typ;
        result := true;
      end
    else
      result := false;
end;
// wobei GetBauteil so aussieht
function TBauteilListe.GetBauteil(ID: string): PBauteil;

  procedure Rekursiv(p: PBauteil; Search: string; var result: PBauteil);
  var i: integer;
  begin
    if p <> nil
      then
        if p^.ID = Search
          then
            result := p
          else
        if p^.Next <> nil
          then
            for i := low(p^.next) to high(p^.next) do
              Rekursiv(p^.next[i],Search,p);
  end;

begin
  Result := nil;
  Rekursiv(FRoot,ID,Result);
end;// Man Gibt also bei den Parent (also Vorgänger) des Einzufügenden Bauteils an, dann wird das Dynamische Array of Pointer um eins erweitert und ein Neues Bauteil eingefügt
Bis dahin klappts auch, aber bei dieser Methode knallts, weil die Stringlist leer ist, obwohl ich per Breakpoint gesehen habe, dass die Inhalte ewrkannt werden
Delphi-Quellcode:
function TBauteilListe.GetLines: TStringlist;

  procedure Rekursiv(p: PBauteil; var Lst: TStringlist);
  var i: integer;
  begin
    if p <> nil
      then
        begin
          if p^.Next <> nil
            then
              for i := low(p^.next) to high(p^.next) do
                begin
                  Rekursiv(p^.next[i],Lst);

                end;
          Lst.Add(p^.ID) // #1 Hier wird die ID hinzugefügt, was ich mit Breakpoint herausfand
        end;
  end;

var Lst: TStringlist;
begin
  Lst := TStringList.Create;
  Lst.Clear;
  Rekursiv(FRoot,Lst);
  Result := Lst; // Das Result ist leer, und list ist auch leer, obwohl an #1 mein Hinzugefügter EIntrag zu sehen ist
  Lst.Free;
end;
Was mache ich bei der benutzung der Stringlist falsch? Daran wirds wohl liegen, denn der Fehler tritt genau dann auf, wenn er die Listbox1.Items setzt, und zwar auf das Result, das trotzdem nur den wert
Result = () Danke schonmal für die Hilfe!

Richard

Edit: Ich habe mal den Titel geändert, das Problem bezieht sich ja gar nicht auf die Pointer
Edit: Titel nochmals geändert, jetzt sinds doch Pointer
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:21
1. Gib mal den Pointer der Tstringlist mit const (statt var) über. Ich bin mir zwar nicht sicher, ob das wirklich einen Unterschied macht. Ich finds besser.

2. Stell dir vor du erstellst die Liste an Adresse A.
Dann übergibst du diese Adresse an Result (also steht in Result A drinn). Soweit ist alles klar. Jetzt löschst du die liste mit lst.free. Result zeigt immer noch auf A, aber dort steht nix mehr drinn.
--> Lass mal das Löschen(freigeben) weg. Das machst du besser nachdem du das Result in der aufrufenden Funktion verarbeitet hast.
Besser ist noch du benutzt von anfang an Result:
Delphi-Quellcode:
function TBauteilListe.GetLines: TStringlist;
...
begin
  Result := TStringList.Create;
  Result.Clear; //ist denk ich nicht zwingend notwendig
  Rekursiv(FRoot,Result);
  //free übernimmt die aufrufende Funktion
end;
...
//Aufrufende Funktion:
var ergebnis:TStringlist;
begin
  ergebnis:=getlines;
  // mit ergebnis arbeiten
  ergebnis.free;
end;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:26
var Lst: TStringlist;
begin
Lst := TStringList.Create;
Lst.Clear;
Rekursiv(FRoot,Lst);
Result := Lst; // Das Result ist leer, und list ist auch leer, obwohl an #1 mein Hinzugefügter EIntrag zu sehen ist
Lst.Free; // meines Erachtes löscht Du hiermit auch die Referenz auf die Result zeigt.
end;

Delphi-Quellcode:
var Lst: TStringlist;
begin
  result:=TStringList.create;
  Lst := TStringList.Create;
  Lst.Clear;
  Rekursiv(FRoot,Lst);
  Result.Text := Lst.Text;
  Lst.Free;
end;
Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#4

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:28
Hallo Richard,

den gröbsten Schnitzer hat dir sirius bereits mitgeteilt. Lines ist bei dir als read-only property vereinbart, aber es ist von seiner Bedeutung her gar keine property. Du erzeugst bei jedem Aufruf eine neue StringList - denkst du daran sie auch wieder zu zerstören? Wenn du alle Bauteile einer Baugruppe (bill-of-material) rekursiv ermitteln und als StringList zurückgeben möchtest, dann hast du zwei bessere Möglichkeiten: Du stellst eine public function CreateList: TStringList zur Verfügung und achtest darauf, dass du diese List zu gegebener Zeit auch wieder freigibts, oder du verwaltest die Liste außerhalb der Methode und übergibst die Liste beim Aufruf. Die Methode kann dann eine public procedure MakeList(s: TStrings) sein.

Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:29
Zitat von "Klaus01
[code=delphi
:
var Lst: TStringlist;
begin
result:=TStringList.create;
Lst := TStringList.Create;
Lst.Clear;
Rekursiv(FRoot,Lst);
Result.Text := Lst.Text;
Lst.Free;
end;[/code]
@Klaus
Wie du an meinem Post siehst, dein Gedanke ist meinem gleich. Aber deine Lösung funktioniert so nicht, da du von Result auch mal mit den Constructer aufrufen solltest.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von Tormentor32
Tormentor32

Registriert seit: 27. Okt 2005
Ort: Düsseldorf
369 Beiträge
 
Delphi XE5 Professional
 
#6

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:35
Delphi-Quellcode:
function TBauteilListe.GetLines: TStringlist;

  procedure Rekursiv(p: PBauteil; var Lst: TStringlist);
  var i: integer;
  begin
    if p <> nil
      then
        begin
          if p^.Next <> nil
            then
              for i := low(p^.next) to high(p^.next) do
                begin
                  Rekursiv(p^.next[i],Lst);
                end;
          Lst.Add(p^.ID)
        end;
  end;

var Lst: TStringlist;
begin
  Result := TStringList.Create;
  Lst := TStringlist.Create;
  Result.Clear;
  Lst.Clear;
  Rekursiv(FRoot,Lst);
  Result := lst;
end;
So scheint das zu Funkrionieren aber:
Result := Lst; Was ist mit dem Speicher, auf den der Pointer vorher gezeigt hat?
Und wenn ich Result oder Lst freigebe, dann dann ist das Result ja wieder nil, folglicherweise müsste es dann doch wider krachen oder? Wo kann ich die Listen wieder freigeben? Das habe ich noch nicht ganz verstanden
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:38
Schmeiss das Lst ganz raus und benutze nur Result (ist ne ganz normale Variable, die nicht definiert werden muss), oder wozu brauchst du zwei Listen?

und mach mal daraus
procedure Rekursiv(p: PBauteil; var Lst: TStringlist);
dass hier
procedure Rekursiv(p: PBauteil; const Lst: TStringlist);
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:43
... wenn er deinem Rat folgt, hat er kein Result mehr in der Methode.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#9

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 08:58
Zur Verdeutlichung meines Hinweises aus Beitrag #4:

Delphi-Quellcode:
procedure TBauteilListe.MakeList(const s: TStrings);

  procedure FetchItem(p: PBauteil);
  var
    i: integer;
  begin
    if Assigned(p.Next) then
      for i := Low(p.Next) to High(p.Next) do
        if Assigned(p.Next[i]) then
          FetchItem(p.Next[i])
    else s.Add(p.ID)
  end;

begin
  s.Clear;
  FetchItem(FRoot);
end;
Freundliche Grüße
  Mit Zitat antworten Zitat
Benutzerbild von Tormentor32
Tormentor32

Registriert seit: 27. Okt 2005
Ort: Düsseldorf
369 Beiträge
 
Delphi XE5 Professional
 
#10

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 09:08
Ich habe aus den Funktionen Prozedure gemacht, wie es scheint ist rekursion bei Funktionen nicht immer optimal...
Jedenfalls funktionierts jetzt

Danke für eure Hilfe!
Richard Mahr
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


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 05:44 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