Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit einer Stringlist und Pointern (https://www.delphipraxis.net/84088-problem-mit-einer-stringlist-und-pointern.html)

Tormentor32 11. Jan 2007 08:00


Problem mit einer Stringlist und Pointern
 
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
Delphi-Quellcode:
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 :spin2:

sirius 11. Jan 2007 08:21

Re: Problem mit einer Stringlist
 
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;

Klaus01 11. Jan 2007 08:26

Re: Problem mit einer Stringlist
 
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

marabu 11. Jan 2007 08:28

Re: Problem mit einer Stringlist
 
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

sirius 11. Jan 2007 08:29

Re: Problem mit einer Stringlist
 
Zitat:

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. :zwinker:

Tormentor32 11. Jan 2007 08:35

Re: Problem mit einer Stringlist
 
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:
Delphi-Quellcode:
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

sirius 11. Jan 2007 08:38

Re: Problem mit einer Stringlist
 
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);

Muetze1 11. Jan 2007 08:43

Re: Problem mit einer Stringlist
 
... wenn er deinem Rat folgt, hat er kein Result mehr in der Methode. :gruebel:

marabu 11. Jan 2007 08:58

Re: Problem mit einer Stringlist
 
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

Tormentor32 11. Jan 2007 09:08

Re: Problem mit einer Stringlist
 
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!

sirius 11. Jan 2007 09:21

Re: Problem mit einer Stringlist
 
Zitat:

Zitat von Muetze1
... wenn er deinem Rat folgt, hat er kein Result mehr in der Methode. :gruebel:

Das bezog sich auf die nested procedure. :evil:


Also nochmal zusammengefasst:
Delphi-Quellcode:
function TBauteilListe.GetLines: TStringlist;

  procedure Rekursiv(p: PBauteil; const 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;

begin
  result := TStringList.Create;
  Rekursiv(FRoot,result);
end;

Tormentor32 11. Jan 2007 10:31

Re: Problem mit einer Stringlist
 
Ich hab schon wieder ein Problem, das aber nicht mit der Stringlist zusammenhängt, sondern mit Pointern (denke ich)

Ich habe meinen Startpunkt FRoot, dessen Eigenschaften im Create gesetzt werden
Delphi-Quellcode:
constructor TBauteilListe.Create;
begin
  inherited create;
  FList := TStringlist.Create;
  new(FRoot);
  FRoot^.ID := 'root';
  FRoot^.Typ := bttRoot;
end;
Die ID ist also 'root'

Es sind meiner Meinung nach noch Fehler in der Methode, die das Bauteil über die ID sucht und in der Methode, die ein neues Bauteil anhängt. Ich habe eine Listbox, in der mir die Bauteile angezeigt, die Liste zeigt alle Bauteile an, die hinzugefügt habe, ich habe im OnClick Ereignis eine Methode, die in drei Labels den Namen des ausgewählten Bauteils, die übergeordneten Bauteile und die untergeordneten Bauteile zurückliefert.

Egal, was ich suche, ich kriege immer nur 'root' zurück

hier die Methoden
Delphi-Quellcode:
function TBauteilListe.GetBauteil(ID: string): PBauteil;
begin
  GetPBauteil(ID);
  Result := FPBauteil; // Dies ist eine Private variable meiner Klasse, deren Wert in GetPBauteil gesetzt wird
end;

procedure TBauteilListe.GetPBauteil(ID: string);

  procedure Rekursiv(p: PBauteil; Search: string; var result: PBauteil);
  var i: integer;
  begin
    if p <> nil
      then
        if p^.ID = Search // Durch breakpoints sah ich, dass ich über die Rekursion bis hierhin gekommen bin, jedoch hat result, also FPBauteil danach immer noch den gleichen Wert!!!
          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
  Rekursiv(FRoot,ID,FPBauteil);
end;
Was ist hier falsch?

sirius 11. Jan 2007 11:00

Re: Problem mit einer Stringlist
 
1. Du hast wahrscheinlich vergessen FRoot^.next auf nil zu setzen (in Create)

2. Result als Variable zu deklarieren ist gefährlich, da es ein reserviertes Wort für Funktionsergebnisse ist. Vielleicht liegts daran. (Ich glaub, jetzt hab ich dich über die Verwendung von Result verwirrt :drunken: )

Tormentor32 11. Jan 2007 11:12

Re: Problem mit einer Stringlist und Pointern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habs geändert, immer noch das Gleiche :(

Im Anhang mal der Source.

Ein Bauteil hinzufügen, auf das Bauteil in der Liste Klicken, Es wird eine Message angezeigt, was gefunden wurde 'root', noch ein Bauteil hinzufügen, das oberste anklicken, AV!

Ich weiß nicht mehr weiter...

sirius 11. Jan 2007 12:26

Re: Problem mit einer Stringlist und Pointern
 
Ich hab mal kurz durchgesucht. Also bis jetzt war für mich auf Anhieb nicht zu erkennen, was du mit was und wo bezweckst. Das ist jetzt vielleicht auch nicht wichtig.

Ich hab mal deinen Fehler eingegrenzt, er passiert hier:
Delphi-Quellcode:
       if p^.Next <> nil
          then
            for i := low(p^.next) to high(p^.next) do
              Rekursiv(p^.next[i],Search,p);
1. (Hat nicht direkt mit dem Fehler zu tun) Du kannst statt "if p^.next<>nil" bess die Länge des Arrays überprüfen if "length(p^.next)>0". Wobei ich mir grad die Frage stelle, ob das überhaupt sein muss, da im anderen Fall die Schleife einfach nie durchlaufen würde.

2. Da ich jetzt den Quelltext besser kenne, sehe cih, dass mein vorheriger Hinweis "FRoot^.Next := nil;" zu setzen nicht sinnvoll ist. Wenn dann eher setlength(FRoot^.next,0);
Das next ist ja ein dynamisches Array.

3. Der Fehler tritt auf, wenn in dem Array p^.next mehr als 1 Element drin ist. Das bedeutet, er führt rekursiv min 2 mal durch.
Nun kann es sein, dass er beim 1. mal aufrufen von "Rekursiv(p^.next[i],Search,p); " das p innerhalb der Funktion so ändert, dass p^.next[i] nicht mehr existiert.

Verstanden?

Tormentor32 11. Jan 2007 12:48

Re: Problem mit einer Stringlist und Pointern
 
Zitat:

3. Der Fehler tritt auf, wenn in dem Array p^.next mehr als 1 Element drin ist. Das bedeutet, er führt rekursiv min 2 mal durch.
Nun kann es sein, dass er beim 1. mal aufrufen von "Rekursiv(p^.next[i],Search,p); " das p innerhalb der Funktion so ändert, dass p^.next[i] nicht mehr existiert.

Verstanden?
Ehrlich gesagt nicht :cry:
Delphi-Quellcode:
procedure TBauteilListe.GetPBauteil(ID: string);

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

begin
  Rekursiv(FRoot,ID,FPBauteil);
end;
Das ist die Procedure. Meinst, dass der P ändert? Der soll Rekursiv ja N mal durchführen. wobei N die Anzahl der Einträge im Array ist. P wird doch garnicht angerührt, oder sehe ich das falsch? Und wenn p^.next[i] nicht mehr existiert, warum zeigt er es dann noch in der Liste an? er aktualisiert die Liste ja mit jedem neuen Eintrag...

Jedenfalls danke dass du drübergeschaut hast!

sirius 11. Jan 2007 14:09

Re: Problem mit einer Stringlist und Pointern
 
Das ist definitv so. Rekursiv zu programmiern, ist leider immer etwas um die Ecke denken und zu beschreiben ist es ganz kompliziert

Angenommen rekursiv wird das erste mal gestartet:
-in p^.next sind zwei Elemente drin
-->die Schleife wird zweimal durchlaufen (soweit ist sicherlich klar)

1. Schleifendurchlauf (denk drann, dein p ist ein var-parameter wird also zurückgegeben)
( p zeigt auf Adresse X; es gibt ein x.next[0] und ein x.next[1] )
( i=0 )
Rekursiv(p^.next[ i],Search,p); --> Rekursiv(x.next[0],Searc,p);
innerhalb diese Funktionsaufrufes wird p verändert (p zeigt jetzt auf Y)

2. Schleifendurchlauf
( p zeigt auf Adresse Y; es gibt kein y.next[0] und kein y.next[1] )
( i=1 )
Rekursiv(p^.next[ i],Search,p); --> Rekursiv(y.next[1],Searc,p);

===> Fehler da y.next[1] nicht existiert

Tormentor32 11. Jan 2007 14:18

Re: Problem mit einer Stringlist und Pointern
 
Dein Ausführungen sind zwar schlüssig, aber sie Passen nicht zu meiner Prozedur
Delphi-Quellcode:
procedure TBauteilListe.GetPBauteil(ID: string);

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

begin
  Rekursiv(FRoot,ID,FPBauteil);
end;
Denn wie du siehst wird MyResult als var parameter übergeben, aber var parameter wird ausschließlich in der Zeile "MyResult := p" verändert, wobei P ja wohl nicht von diesem Ausdruck verändert wird

oder etwa doch???

sirius 11. Jan 2007 14:37

Re: Problem mit einer Stringlist und Pointern
 
Doch, ich habs ja mit dem Debugger durchlaufen lassen.

Denk immer daran, die Funktion ist Rekursiv, ruft sich also selber wieder auf. Und das kann n-mal passieren (bis der Stack voll ist)
In unserem Fall reichen zwei Ebenen. Also angenommen es gibt rekursiv1 und rekursiv2:

Delphi-Quellcode:
procedure Rekursiv2(p: PBauteil; Search: string; var MyResult: PBauteil);
  var i: integer;
  begin
    if p <> nil
      then
        if p^.ID = Search
          then
            MyResult := p //hier veränderst du MyResult und damit p in Rekursiv1
          else
        if length(p^.Next) > 0 
          then
            for i := low(p^.next) to high(p^.next) do
              Rekursiv3(p^.next[i],Search,p);
  end;
Delphi-Quellcode:
procedure Rekursiv1(p: PBauteil; Search: string; var MyResult: PBauteil);
  var i: integer;
  begin
    if p <> nil
      then
        if p^.ID = Search
          then
            MyResult := p
          else
        if length(p^.Next) > 0 
          then
            for i := low(p^.next) to high(p^.next) do
              Rekursiv2(p^.next[i],Search,p); //<--- hier ist der Absturz beim 2. Schleifendurchlauf
  end;
Versuch jetzt mal gedanklich durch den Code durchzusteigen. Das Problem liegt innerhalb von Rekursiv1, und zwar beim Aufruf von Rekursiv2.
Ob nun Rekursiv 1, sich selber oder Rekursiv2 aufruft, ist dabei egal. Man programmiert natürlich so, dass er sich selber aufruft. Darum nennt man es ja auch rekursiv.

Der Start der Rekursion erfolgt mit
Delphi-Quellcode:
Rekursiv1(FRoot,ID,FPBauteil);
Edit: Leider habe ich nicht erkannt, was aus dieser Funktion, das Ergebnis sein soll, deswegen kann ich es dir auch nicht umschreiben.

Tormentor32 11. Jan 2007 14:44

Re: Problem mit einer Stringlist und Pointern
 
Aber warum ändert sich P, wenn ich nur MyResult ändere? Das will mir irgendwie nicht in den Kopf gehen... :wall:
Delphi-Quellcode:
procedure TBauteilListe.GetPBauteil(ID: string);

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

begin
  Rekursiv(FRoot,ID,FPBauteil); // FPBauteil ist das Ergebnis, ein Pointer, der Auf das gefundene bauteil zeigt, Private Variable Meiner Klasse, die Klasse sieht so aus:
end;
type
  TBauteilListe=class(Tobject)
  private
    FRoot,
    FPBauteil: PBauteil;
    FList: TStringlist;
    function GetBauteil(ID: string): PBauteil;
    function GetText: string;
    procedure GetPBauteil(ID: string);
    procedure SetLines(var MyResult: TStringlist);
    procedure NilBauteile;
  public
    constructor Create;
    destructor Destroy; override;
    function Attach(ParentID,ChildID: string): boolean;
    function AddBauteil(ID: string; Typ: TBauteilTyp; Parent: string): boolean;
    property Items[ID: string]: PBauteil read GetBAuteil;
    property Text: string read GetText;
  end;
Ich blick da einfach nicht durch, warum das mit P so ist, und weiß nicht wie ich es anders machen kann, sitzt da jetzt seit nen paar stunden dran, es wäre nett, wenn du mir das umschreiben könntest...

sirius 11. Jan 2007 14:53

Re: Problem mit einer Stringlist und Pointern
 
ok anders,

folgender Code:

Delphi-Quellcode:
procedure dummy(var x:integer);
begin
  x:=5;
end;

procedure testdummy;
var p:integer;
begin
  p:=3;
  dummy(p);
  //Na? Welchen Wert hat p an dieser Stelle?
end;
p ist an der Stelle 5. Das liegt an diesem "var" vor dem x in der Prozedurendeklaration.

Soweit klar?

Tormentor32 11. Jan 2007 14:57

Re: Problem mit einer Stringlist und Pointern
 
Zitat:

Zitat von Tormentor32
Aber warum ändert sich P, wenn ich nur MyResult ändere? Das will mir irgendwie nicht in den Kopf gehen... :wall:
Delphi-Quellcode:
procedure TBauteilListe.GetPBauteil(ID: string);

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

begin
  Rekursiv(FRoot,ID,FPBauteil); // FPBauteil ist das Ergebnis, ein Pointer, der Auf das gefundene bauteil zeigt, Private Variable Meiner Klasse, die Klasse sieht so aus:
end;
Ich blick da einfach nicht durch, warum das mit P so ist, und weiß nicht wie ich es anders machen kann, sitzt da jetzt seit nen paar stunden dran, es wäre nett, wenn du mir das umschreiben könntest...

Aber bei P steht KEIN var davor! Wie das mit dem var funktioniert ist mir klar, aber ich verstehe nicht, warum P (ich meine nicht MyResult) geändert wird, wenn ich sage MyResult := P!

sirius 11. Jan 2007 15:14

Re: Problem mit einer Stringlist und Pointern
 
Doch, doch, doch, doch! :duck: :spin:

p ist der dritte parameter. Also wird er zu MyResult im zweiten aufruf. In diesem zweiten Aufruf wird myresult geändert, damit wird p geändert, wenn die Funktion aus Rekursiv (2. Ebene) wieder zurückspringt nach Rekursiv1

geh nochmal gedanklich, dass durch, was ich dir in Post #19 geschrieben habe.

Tormentor32 11. Jan 2007 15:18

Re: Problem mit einer Stringlist und Pointern
 
OOHHH MANNNN ICH BIN SOO BLÖÖÖÖÖDDDDD!!!!!!!

Da muss natürlich MyResult hin! Jetzt klappt das schonmal mit dem Suchen und so! Mannometer ich könnte :wall: ich sitz stunden da dran und dann hab ich nur die Falsche Variable übergeben :kotz:

DANKE DANKE DANKE :love: :love: :love:

sirius 11. Jan 2007 15:24

Re: Problem mit einer Stringlist und Pointern
 
Und ich hab einfach nicht kapiert, was du mit dieser funktion willst. Aber jetzt sieht es schon etwas klarer aus.

Tormentor32 11. Jan 2007 15:29

Re: Problem mit einer Stringlist und Pointern
 
Dadurch, dass MyResult da nicht drinstand, war natürlich Chaos vorprogrammiert...

Jedenfalls nochmal vielen Dank, ich dachte, du wolltest mir die ganze Zeit sagen, dass durch


MyResult := P

Sich P verändert...

Tormentor32 12. Jan 2007 08:10

Re: Problem mit einer Stringlist und Pointern
 
Schon wieder diese Pointer...

Aaaaalso

Ich habe die Einträge in meiner Liste jetzt so arrangiert:
Delphi-Quellcode:
  TBauteil = Record
    ID: string; // Der einzigartige name jedes Bauteils
    Typ: TBauteilTyp; // Der Typ des Bauteils (im moment noch unwichtig)
    Ebene: integer; // Die Ebene des Bauteils, also Root Ebene = 0 Nachfolger Ebene = 1 usw
    Parent,Next: Array of PBauteil // Die direkten nachfolgenden und vorherigen Elemente
  end;
Da ich mit meiner Liste einen Stromkreis darstellen möchte, habe ich mir Überlegt, dass sich Parallel und Reihenschaltungen ja auch verschachteln können z.B:
Code:

[root] ---> [root_child1] ---> [root_child1_child1] ---> [root_child1_child1_child1]
                          \--> [root_child1_child2] --/
In diesem Fall wird aber durchs rekursive Auflisten (logischerweise, ergeht ja alle einträge durch, folgendes Angezeigt
Zitat:

Zitat von Listbox
root_child1_child1_child1
root_child1_child1
root_child1_child1_child1
root_child1_child2
root_child1
root

Ist ja auch klar, denn durch die Rekursive Suche wird root_child1_child1_child1 zweimal gefunden

Wie kann ich das umgehen?
Die Zweite Sache ist, wenn ich den Speicherplatz beim beenden rekursiv freigebe, dann kommts auch zu einem Problem, denn:
Code:
[s][root] ---> [root_child1] ---> [root_child1_child1] ---> [root_child1_child1_child1][/s]
[s]                         \--> [root_child1_child2] --/[/s]

[s][root] ---> [root_child1] ---> [root_child1_child1] ---> nil[/s]
[s]                         \--> [root_child1_child2] [color=#ff0000][b]--/[/b][/color] // der Zeigt dahin, wo nichts ist und es kracht, wenn er versucht auf dieses Element zuzugreifen, er weiß ja nicht, das es das Element nicht mehr gibt [/s]
Wie kann ich das verhindern?

Und nochwas? Wäre es sinnvoller, statt Parent: Array of string; lieber Parent: Array of PBauteil; zu nehmen? EDIT: hat sich erldedigt, nur noch das Erste

Vielen Dank schonmal für die Hilfe!

Richard

sirius 12. Jan 2007 09:21

Re: Problem mit einer Stringlist und Pointern
 
:warn: Man sollte halt immer vor dem Programmieren über das Konzept nachdenken. Aber ich programmiere auch häufig nur drauf los. Grade, wenn man nur etwas üben oder lernen möchte. Und wenn man eben nur lernt, sich vorher ein vollständiges Konzept zu erarbeiten. :coder2: :roteyes:

Mit deinem Programmaufbau fällt mir auf Anhieb nicht viel ein. Du könntest einfach im nachhinein Duplikate löschen. Weis nicht ob das dir ausreicht.

Oder du machst es so wie in PSpice (und wahrscheinlich an allen anderen Netzberechnungsprogrammen auch):
Da hat jedes Element 4 ( oder 3) Kenngrößen:
1. Was ist es (Widerstand, Quelle, Spule)
2. welche Größe hat es (10V, 2ohm); wobei die Einheit anhand der Art des Elementes zu erkennen ist
3.1. Wo beginnt es
3.2. Wo endet es

zu3) Dabei beziehst du dich immer auf Netzknotenpunkte, die du einfach durchnummerierst

Ich hab irgendwo (noch in Turbo Pascal 6.0) ein Programm geschrieben, was einfache Pspice-Dateien einlesen konnte und berechnen konnte. Die Dateien hatten etwa folgenden Inhalt:
  • R 10 0 1 //Widerstand 10ohm von Knoten 0 zu Knoten 1
  • I 5 0 1 //Stromquelle 5A von Knoten 0 zu Knoten 1
  • R 2 1 2 //Widerstand 2ohm von Knoten 1 zu Knoten 2
usw.
Das konnte man dann ganz einfach in die Netzberechnungsgleichungen (bzw. Matrix) schreiben.

Tormentor32 12. Jan 2007 09:39

Re: Problem mit einer Stringlist und Pointern
 
Ich hab das Problem schon gelöst: Beim Suchen wird geschaut, ob der Erste Vorgänger des Nachfolgers das momentane Element ist, und nur dann wird rekursiv wieder aufgerufen.
Zitat:

Zitat von sirius
Man sollte halt immer vor dem Programmieren über das Konzept nachdenken. Aber ich programmiere auch häufig nur drauf los. Grade, wenn man nur etwas üben oder lernen möchte. Und wenn man eben nur lernt, sich vorher ein vollständiges Konzept zu erarbeiten.

Ja da hast du wohl recht, doch wenn ich jetzt das Konzept ändere, dann war ja alles für die Katz, außerdem finde ich die Idee, wie ich das gemacht habe gar nicht so schlecht... (hast du auch nicht gesagt) :roteyes:

naja jedenfalls Danke für die (nicht) Hilfe (diesmal habichs allein hingekriegt! :bounce2: )

Richard

sirius 12. Jan 2007 09:44

Re: Problem mit einer Stringlist und Pointern
 
:gruebel: Bist du sicher, dass das klappt. Was ist, wenn das Netz hinter [root_child1_child2] nicht gleich wieder zusammengeht, sondern erst noch ein paar andere Elemnte kommen...

Tormentor32 12. Jan 2007 09:56

Re: Problem mit einer Stringlist und Pointern
 
Ja, das sollte eigentlich klappen:
Code:
[root] -> [root_1] -> [root_1_1] -> [root_1_1_1] -> [root_1_1_1_1]
                   \> [root_1_2] -> [root_1_2_1] -/

=> Wenn die Rekursion bei Element [root_1_2_1] angelangt ist passiert folgendes:
[root_1_2_1]^.next[i]^.Parent[0] <> [root_1_2_1]
Jedes Element außer [root] hat ja einen Parent, und wenn ein Element mehr als einen Parent hat, dann wird einfach geprüft, ob das Element und der erste Parent des Nachfolgers gleich sind, wenn das so ist, kann das bedeuten:
A: Es gibt nur einen Parent des Nachfolgers, der logischerweise das gerade aktive Element ist: Suche wird fortgesetzt
B: Es gibt mehrere Parents und der Parent des Nachfolgers ist das gerade aktive Element: Suche wird fortgesetzt
C: Es gibt mehrere Parents und der Parent des Nachfolgers ist nicht das gerade aktive Element: Such wird mit dem Nächsten Nachfolgers des Elements, bzw wenn kein weiteres vorhanden ist in der Nächst höheren Rekursionsebene weitergeführt


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