TStringList
  Jedną z bardziej użytecznych klas w BCB jest klasa TStringList, która nie występuje w postaci komponentu ani nie wymaga dołaczania do projektu, lub definiowania w sekcji include ponieważ jest automatycznie dołączana w zależności od potrzeb. Klasa TStringList jest wykorzystywana między innymi w komponentach TListBox, TComboBox, TListView, itp...
Zasługuje ona na szczególną uwagę, ponieważ ułatwia pracę na obiektach zawierających łańcuchy znaków, zmienne typu String. Klasa TStringList jest swego rodzaju listą przechowującą wartości typu String i zawierającą wskaźnik do każdego wiersza listy.
  Rozważmy sytuacją w której potrzebujemy przechować w pamięci listę nazwisk, np.:

  • Angelika Jolii
  • Sandra Bulloc
  • Stanisław Tym
  • Harrison Ford
  • Sylvester Stallone
  • Arnold Schwarcenneger

    Najprostszym rozwiązaniem jakie nasuwa się przy próbie zapisania tej listy w pamięci, to jest stworzenie sześciu zmiennych typu String i przypisanie im określonych wartości, np.:

    String a1 = "Angelika Jolii";
    String a2 = "Sandra Bulloc";
    String a3 = "Stanisław Tym";
    String
    ...i tak dalej...

    Takie rozwiązanie jest mało praktyczne, ponieważ wewnątrz programu trzeba stworzyć określioną liczbę zmiennych i można zapamiętać tylko tyle rekordów ile zmiennych zostało zadeklarowanych, dlatego znacznie lepszym rozwiązaniem jest posłużenie się klasą TStringList, ponieważ może ona przechowywać dowolną liczbę rekordów i nie trzeba z góry określać ile ich będzie.

    Menu


    Dodawanie rekordów do obiektu typu TStringList

      W celu umieszczenia listy zawierającej wartości typu String w obiekcie typu StringList należy go najpierw stworzyć:

     TStringList *Lista = new TStringList;


    W przykładzie został utworzony nowy obiekt typu StringList o nazwie Lista (nazwa jest dowolna). Żeby dodać do listy rekordy należy posłużyć się funkcją Add:

     TStringList *Lista = new TStringList;

     Lista->Add("Angelika Jolii");
     Lista->Add("Sandra Bulloc");
     Lista->Add("Stanisław Tym");


    W celu pobrania określonej wartości z obiektu Lista należy posłużyć się funkcją String, przy czym należy podać numer wiersza, którego wartość chcemy odczytać:

     Edit1->Text     = Lista->Strings[0];
     String abc      = Lista->Strings[2];
     Label1->Caption = Lista->Strings[1];


    Należy zawsze pamiętać o tym, żeby usunąć z pamięci wszystkie stworzone przez nas obiekty typu StringList gdy nie będą już potrzebne. Można to zrobić na dwa sposoby:

    Sposób 1.:

     Lista->Free();


    Sposób 2.:

     delete Lista;


    ...powrót do menu. 


    Zapisywanie zawartości obiektu typu TStringList do pliku

      Zapisywanie zawartości obiektu typu TStringList do pliku jest bardzo proste i ogranicza się w zasadzie do wywołania funkcji SaveToFile i przekazaniu jej jako parametru nazwy pliku. Można się w tym celu posłużyć dodatkowo obiektem TSaveDialog, który umożliwi zapisanie nam pliku pod dowolną nazwą i w dowolnym miejscu na dysku. Zanim zapiszemy zawartość listy do pliku dobrze jest coś w niej umieścić, ale najpierw należy ją utworzyć. W tym celu przchodzimy do pliku nagłówkowego (np. Unit1.h) i w sekcji private deklarujemy obiekt typu TStringList o nazwie Name:

    // Plik nagłówkowy np. Unit1.h.
    //--------------------------------
    private:
           TStringList *Name;
    //--------------------------------


    I to tyle jeśli chodzi o plik nagłówkowy. Teraz przechodzimy do pliku źródłowego (np. Unit1.cpp) i definiujemy nowo utworzony typ:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    #include <vcl.h>
    #pragma hdrstop

    #include "Unit1.h"
    //--------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //--------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
     Name = new TStringList;
    }
    //--------------------------------


    Następnie np. w zdarzeniu 'OnClick' przycisku Button1 wprowadzamy do listy jakieś wartości:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Name->Add("Agnieszka");
     Name->Add("Dorota");
     Name->Add("Iwona");
     Name->Add("Basia");
     Name->Add("Małgorzata");
     Name->Add("Beata");
    }
    //--------------------------------


    Następnie np. w zdarzeniu 'OnClick' przycisku Button2 wywołujemy okno dialogowe SaveDialog1 i zapisujemy zawartość listy do pliku tekstowego:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     if(SaveDialog1->Execute())
        Name->SaveToFile(SaveDialog1->FileName);
    }
    //--------------------------------


    Zawartość listy zawsze jest zapisywana do pliku w trybie tekstowym.
    Na zakończenie należy pamiętać o usunięciu obiektu Name z pamięci. Najlepiej jest to zrobić w chwili zamknięcia programu:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
     Name->Free();
    }
    //--------------------------------


    ...powrót do menu. 


    Wczytywanie danych z pliku do obiektu typu TStringList

      Do obiektu typu TStringList można wczytywać dane tylko z plików zapisanych w trybie tekstowym. Pliki zapisane w trybie binarnym również zostaną wczytane, lecz będzie to zbiór niezrozumiałych znaków. Wczytywanie odbywa się w sposób analogiczny do zapisywania (patrz: Zapisywanie zawartości obiektu typu TStringList do pliku) z tą jednak różnicą, że należy posłużyć się funkcją LoadFromFile(AnsiString FileName):

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     TStringList *Lista = new TStringList;

     if(OpenDialog1->Execute())
        Lista->LoadFromFile(OpenDialog1->FileName);
    }
    //--------------------------------


    ...i to w zasadzie wszystko, zawartość pliku tekstowego wybranego w oknie dialogowym OpenDialog zostanie wczytana do obiektu Lista typu TStringList.

    ...powrót do menu. 


    Przepisywanie zawartości obiektu typu TStringList do obiektu ListBox

      Załóżmy że wczytaliśmy lub dodaliśmy do obiektu typu TStringList jakieś dane (rekordy), są one obecne w pamięci lecz ich nie widać, można na przykład pobierać pojedyncze wartości i wyświetlać je w np. obiekcie Edit1. Co jednak jeśli chcemy wyświetlić całą zawartość obiektu typu StringList? Najlepiej w takiej sytuacji jest przepisać jego zawartość do obiektu ListBox. Można to zrobić posługując się pętlo for np.:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     TStringList *Lista = new TStringList;

     if(OpenDialog1->Execute())
        {
          Lista->LoadFromFile(OpenDialog1->FileName);

          for(int i = 0; i < Lista->Count; i++)
          {
              ListBox1->Items->Add(Lista->Strings[i]);
          }

        }
     delete Lista;
    }
    //--------------------------------


    W podanym przykładzie pojawił się nowy element Count. Jest to właściwość typu int, która nie pobiera żadnych parametrów lecz zwraca wartość liczbową typu int będącą w tym konkretnym przypadku liczbą wierszy zawartych w obiekcie Lista.
     Cóż takiego właściwie dzieje się w podanym przykładzie? Otórz po wczytaniu do obiektu Lista danych z pliku zostaje uruchomiona pętla, która działa toputy, dopuki w obiekcie Lista znajdują się się wiersze zawierające jakieś wartości, następnie wewnątrz pętli zawartość poszczególnych wierszy obiektu Lista zostaje przepisana do obiektu ListBox1, a na koniec obiekt Lista zostaje usunięty z pamięci.
     Taki sposób przepisywania zawartości z obiektu Lista do obiektu ListBox1 ma pewną wadę, otóż jak zapewne wszyskim wiadomo, każda pętla opóżnia działanie programu i przez to jest mało efektywna. Tak więc rodzi się pytanie - czy można to zrobić inaczej i szybciej?
      Tak!
    Właściwość Items obiektu ListBox1 jest typu TStringList więc można jej bezpośrednio przypisać zawartość obiektu Lista:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     TStringList *Lista = new TStringList;

     if(OpenDialog1->Execute())
       {
         Lista->LoadFromFile(OpenDialog1->FileName);

         ListBox1->Items = Lista;
       }

     delete Lista;
    }
    //--------------------------------


    Oczywiście rozwiązanie, które tutej przedstawiłem ma charakter edukacyjny ponieważ cały problem dałby się rozwiązać znacznie prościej. Chcąc wczytać do obiektu ListBox1 zawartość pliki nie trzeba się wcale posługiwać obiektem typu TStringList, ponieważ skoro właściwość Items obiektu ListBox1 jest typu TStringList to można posłużyć się funkcją LoadFromFile wywołując ją bezpośrednio z wałściwości Items:

    // Plik źródłowy np. Unit1.cpp
    //--------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     if(OpenDialog1->Execute())
       {
         ListBox1->Items->LoadFromFile(OpenDialog1->FileName);
       }
    }
    //--------------------------------


    ...powrót do menu. 


    Przepisywanie zawartości obiektu typu TStringList do obiektów zawierających właściwość typu TStringList

      Ta porada ma charakter informacyjny prezentujący obiekty do których można przepisywać zawartość obiektu typu TStringList, a sposób przpisywania jest identyczny z tym zaprezentowanym w poradzie: Przepisywanie zawartości obiektu typu TStringList do obiektu ListBox:

      Obiekt TComboBox:

      ComboBox1->Items = Lista;


      Obiekt TMemo:

      Memo1->Lines = Lista;


      Obiekt TRichEdit:

      RichEdit1->Lines = Lista;


    ...powrót do menu.