Hallo zusammen,
ich bin jetzt ein bischen mehr als zwei Jahre dabei (Delphi5) und das meiste funktioniert auch gut. Allerdings merke ich selbst, dass ich vieles nur so mache, dass es funktioniert ... der Stil ist noch nicht besonders gut und da habe ich mal eine Frage ...
Kurz noch vorne weg:
Wir lesen Daten aus einem Gerät aus (Datensatz ist "string") oder aus Dateien ein (Textdateien, ini, datensatz ist string). Ich arbeite also mit StringListen, wobei der erste "String" der StringList das Datum enthält und danach kommen die anderen Daten. Nun habe ich ja mehrere Datensätse also viele StringListen ... Da habe ich nun angefangen mit TList zu arbeiten. Die Liste aus Stringlisten lässt sich auch recht gut wieder auf der Oberfläche darstellen (TStringGrid).
Nun meine Frage, ob der folgende Code so korrekt ist - der Code ist ein bischen abgekürzt
Delphi-Quellcode:
procedure Dateneinlesen;
var List: TList;
strList: TStringList;
i, j: integer;
begin
List := TList.Create;
try
//gehe Stringgrid durch und merke dir die alten Daten
// StringGrid hat Tabellenkopf
// Anzahl der Spalten ist der Anzahl "Datum + Daten im Datensatz" bereits angepasst
for i:=1 to StringGrid.RowCount-1 do begin
strList := TStringList.Create;
strList.add('0'); //alter Datensatz
for j:=0 to StringGrid.ColCount-1 do begin
strList.add(StringGrid.Cells[j,i]);
end;
List.Add(strList);
end;
//---------
//neue Daten einlesen
// Datei öffnen
...
//Daten einlesen
repeat
strList := TStringList.Create;
strList.add('1'); //neue Daten
strList.add(andere Daten);
List.add(strList);
until keine anderen Daten mehr
//Datei schließen
...
//--------
//Liste nach Datum sortieren ... steht in allen Datensätzen natürlich an der gleichen Stelle
//hier nicht weiter beschrieben
ListeVonStrListenNachDatumSortieren(List,
StrListSpalteDatum, BeginnInListe, EndeInListe);
//Doppelte löschen
ListeVonStrListenDatumDoppelteRaus(List, StrListSpalteDatum);
//--------
//Auf der OF anzeigen
// alte Daten aus StringGrid löschen
StringGrid.RowCount := 2;
for j:=0 to StringGrid.ColCount-1 do begin
StringGrid.Cells[j,1] := '';
end;
//sortierte Daten ohne Doppelte eintragen
for i:=0 to List.Count-1 do begin
if StrinGrid.Cells[0,1] <> '' then StringGrid.RowCount := StringGrid.RowCount +1;
strList := List.Item[i];
for j:=1 to strList.Count-1 do begin
//im ersten Element, steht nur, ob der Datensatz alt oder neu ist ... deshalb bei j=1 anfangen
if j > StringGrid.ColCount-1 then begin
StringGrid.Cells[j, i] := strList.Strings[j];
end else begin
breake; //was auch immer hier noch drin steht, was nicht drin stehen soll
end;
end;
end;
//--------
finally
for i:=0 to List.Count-1 do begin
strList := List.item[i];
strList.free;
end;
List.Free;
end;
end;
Delphi-Quellcode:
procedure ListeVonStrListenDatumDoppelteRaus(List: TList;
StrListSpalteDatum: integer);
var strList1, strList2: TStringList;
i: integer;
begin
if List.Count < 1 then exit;
i:=0;
repeat
strList1 := List.Items[i];
strList2 := List.Items[i+1];
if (strList1.Count > 0) and (strList2.Count > 0) then begin
if strList1.strings[StrListSpalteDatum] = strList2.strings[StrListSpalteDatum] then begin
if strList1.strings[0] = '0' then begin
strList1.free;
List.Delete(i);
end else begin
strList2.free;
List.Delete(i+1);
end;
//Doppelte dürfen/ können nicht da sein
//Entweder das eine oder das andere ist falsch
end else begin
inc(i);
end;
end else begin
inc(i); //sonst komm ich aus der Schleife nicht wieder raum
//aber, was sind das für komische Stringlisten
// strList.Strings[0] = ob alt oder neu
// strList.strings[strListSpalteDatum] = Datum
// und Rest?
end;
until i >= List.Count-2;
//nochmal letzten Beiden kontrollieren
//kann nicht am Anfang der Schleife inc(i) machen, weil
// wenn ein Element/Item gelöscht wird soll er ja nicht hoch zählen
// -> am Ende nochmal kontrollieren
strList1 := List.Items[List.Count-2];
strList2 := List.Items[List.Count-1];
if (strList1.Count > 0) and (strList2.Count > 0) then begin
if strList1.strings[StrListSpalteDatum] = strList2.strings[StrListSpalteDatum] then begin
if strList1.strings[0] = '0' then begin
strList1.Free;
List.Delete(List.Count-2);
end else begin
strList2.Free;
List.Delete(List.Count-1);
end;
end;
end;
end;
Was ist eigentlich, wenn man die StringListen, die in der List stecken, nicht frei gibt und nur List.free macht. Ist der speicher dann noch belegt, aber es zeigt nichts mehr darauf oder kann der Speicher dann wieder verwendet werden, aber es ist einfach schlechter Stil?
Oder muss ich das mit den StringList.free gar nicht machen? In der Hilfe steht nämlich:
"
Soll lediglich die Referenz auf ein Element gelöscht werden, ohne das Element selbst zu entfernen und den Wert von Count zu ändern, setzen Sie die Eigenschaft Items für Index auf nil.
"
Wenn ich mit List.Delete(i) eine Instanz=TstringList lösche, ist dann der Speicher wieder richtig freigegeben oder ist nur der Pointer gelöscht? Wenn ich zuvor schon die StringListe freigegeben habe, hat doch der Pointer gar nichts mehr auf das er in dem Moment zeigt? Oder ist dem Pointer das egal, weil er eh nur auf eine beliebige Adresse im Speicher zeigt?
Wenn euch noch weitere Fehler auffahlen, wäre ich über jede Korrektur sehr dankbar! Z.B. habe ich das Gefühl, dass die Tabelle (StringGrid) nich korrekt gelöscht wird, nur weil ban die Zeilenanzahl zurücksetzt... aber da das ein anderes Thema ist, wollte ich das hier nicht weiter ausmahlen.
Ich danke euch schon mal im Vorraus für den Support.
die Suchende