Hi ich versuche gerade einen Baum durchzugehen und aus jedem Eintrag einen String auszulesen. Die Strings sollen dann schliesslich einer Combobox zugewiesen werden. Dazu packe ich das Ergebnis der Function bereits in eine Stringliste. Die Function ruft sich Rekursiv auf. Demnach werden die Strings immer größer. Leider scheitert aber bereits beim ersten Aufruf der Function jegliche zuweisung. ein result.clear gibt einen ZUgrifffehler, genau wie alle anderen Zugriffe.. Jemand eine Idee??
Announcement
Collapse
No announcement yet.
Funtion mit tstrings als Ergebnis???
Collapse
X
-
Die Delphi-"Standard"-Vorgehensweise für dein Problem wäre,
nicht eine Funktion mit Stringliste als Rückgabewert, sondern eine
Prozedur mit TStrings als Übergabeparameter. In der Routine hängst
du dann nur an die übergebene Liste an. Auf die Tour gibt's weniger
Verwirrung, wer die Liste erzeugen oder zerstören muss, und du sparst
dir einige Kopieraktionen (besonders wenn deine Routine rekursiv sein soll). Beispiel: Standardanwendung mit TMemo, TEdit und TButton drauf, dazu folgender Code:
<pre class="sourcecode"><code>
<b>procedure</b> AddNumbers(AList: TStrings; i: Integer);
<b>begin</b>
AList.Add(IntToStr(i));
<b>if</b> i > 0 <b>then</b>
AddNumbers(AList, i - 1);
<b>end</b>;
<br>
<b>procedure</b> TForm1.Button1Click(Sender: TObject);
<b>begin</b>
Memo1.Clear;
AddNumbers(Memo1.Lines, StrToIntDef(Edit1.Text, 10));
<b>end</b>;
</code></pre>
HTH, Uli
Comment
-
hm....
es klappt nu wunderbar rekursiv. aber die Frage ,mit dem erzeugen und zerstören habe ich mich auch schon gefragt wie das klappt und ob ich da nicht ein paar nette Speicher Leichen lasse. Aber leider habe ich mich mit dem Thema eh erst wenig beschäftigt.
Mein Programm sieht nun wie folgt aus:
<pre>
Function tbaum.drin2: tstrings;
Begin
result := tstringlist.Create;
If inhalt = nil then result.Clear
else Begin
If links = nil then
If rechts = Nil then Begin
result.clear;
result.add(tstring50(inhalt^));
nummer := i;
inc(i);
end
else Begin
result.Clear;
result.add(tstring50(inhalt^));
nummer := i;
inc(i);
result.AddStrings (rechts.drin2);
end
else
If rechts = nil then Begin
result.Clear;
result.add(tstring50(inhalt^));
nummer := i;
inc(i);
result.addStrings (links.drin2);
end
else begin
result.Clear;
result.add(tstring50(inhalt^));
nummer := i;
inc(i);
result.addStrings (links.drin2);
result.addStrings (rechts.drin2);
end;
end;
End;
</pre>
Es wird ein Binärer Baum durchlaufen. Aus jeder "Etage" wird ein String ausgelesen. i ist eine globale variable. Über sie wird jedem gesicherten Eintrag eine eindeutige Zahl zugewiesen. Diese ist gleichzeitig die Position in der Stringliste.
Bisher funktioniert es so ganz gut, frage eben nur: bleibt was im Speicher, wenn ja kann ich es löschen??
Ich hoffe man wird aus meinen Code ein wenig schlau, wüsste nun nicht wie ich das erklären sollte
Bis denne Christophe
Comment
-
Hi Christopher,<br>
ich hab deine Routine jetzt nur mal schnell überflogen, aber ich glaube, du hinterläßt
eine Spur von Leichen <g> hinter dir zurück, z.B. wird in der Zeile
<tt>result.addStrings (links.drin2);</tt> innerhalb von <tt>links.drin2</tt>
eine Stringliste erzeugt (erste Zeile der Routine), diese Liste wird als Übergabeparameter
an AddStrings verwendet, aber nie aufgeräumt. Also wenn du die Stringliste unbedingt
<b>in</b> "Drin2" erzeugen willst, dann muss der Aufruf
wenigstens so ähnlich aussehen:<pre>
TemporaereStringListe := links.drin2;
result.addStrings(TemporaereStringListe);
TemporaereStringListe.Free;
</pre>
Das ist aber IM(NS)HO Quatsch: Bei jeder Rekursionsebene erzeugst du Stringlisten,
kopierst sie, löschst sie wieder -- das ist ein Heidenaufwand zur Laufzeit,
den du dir mit dem Ansatz aus meinem ersten Posting sparen kannst:
Erzeuge <b>eine</b> Stringliste (du willst am Ende ja auch nur eine haben),
und hänge einzelne Strings an, statt komplette Stringlisten zu kopieren.
<p>Was du mit der "Etagennummer" (Variablen i und nummer) anstellst, hab ich nicht
recht kapiert, aber auch da würde ich i.a. einen Übergabeparameter (evtl. per "var" übergeben)
einer globalen Variablen vorziehen -- ähnlich wie das "i" in meinem AddNumbers.
<p>BTW: Nach memory leaks kannst du z.B. mit MemProof suchen (http://www.automatedqa.com/downloads/memproof.asp).
<p>Ciao, Uli
Comment
Comment