Einzelnen Beitrag anzeigen

die Suchende

Registriert seit: 27. Mär 2009
16 Beiträge
 
#1

Gibt TList.Delete darin befindliche Instanzen auch frei oder ?

  Alt 25. Jul 2011, 14:24
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] = '0then 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] = '0then 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
  Mit Zitat antworten Zitat