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 2 von 4     12 34      
Benutzerbild von sirius
sirius

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

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 10:21
Zitat von Muetze1:
... wenn er deinem Rat folgt, hat er kein Result mehr in der Methode.
Das bezog sich auf die nested procedure.


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;
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
 
#12

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 11:31
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?
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Problem mit einer Stringlist

  Alt 11. Jan 2007, 12:00
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 )
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
 
#14

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 12:12
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...
Angehängte Dateien
Dateityp: zip source_782.zip (11,4 KB, 5x aufgerufen)
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 13:26
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?
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
 
#16

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 13:48
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
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!
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 15:09
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
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
 
#18

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 15:18
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???
Richard Mahr
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 15:37
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
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.
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
 
#20

Re: Problem mit einer Stringlist und Pointern

  Alt 11. Jan 2007, 15:44
Aber warum ändert sich P, wenn ich nur MyResult ändere? Das will mir irgendwie nicht in den Kopf gehen...
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...
Richard Mahr
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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 12:36 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