El objeto TString.

21-03-1998

Cuando consultas la documentación del Delphi, muchas veces te encuentras con la palabra "TString" , por ejemplo el componente Tmemo (el que he usado para hacer el editor de texto) dice que su propiedad lines es del tipo TString, o también el componente TlistBox. Pues estos componentes hacen uso de un objeto llamado TString, que no es más que una lista formada por cadenas de caracteres (string). Se podria decir que es una "especie" de Array (matriz o vector) que contiene cadena, pero que nos permite realizar operaciones con sus elementos. Así que en este capítulo voy a explicaros las operaciones que se pueden hacer con este objeto, y decir que son aplicables a todos los componentes que tengan una propiedad de este tipo. Además como estamos trabajando en un entorno orientado al objeto de verdad, si necesitas almacenar una lista cadenas puedes crear este objeto en memoria sin tener que recurrir a un componente, con lo que ahorras memoria y ganas velocidad entre otras ventajas.

Esta es la lista de las operaciones que se pueden realizar:

Contar el número de elementos Acceder a un elemento en particular
Encontrar la posición que ocupa un elemento Añadir un elemento al final.
Mover un elemento Eliminar un elemento
Copiar una lista entera  

Bueno lo primero es saber como añadir un elemento a una lista. Coloca un TEdit, un botón, y un TlistBox en un formulario, los encontraras todos en la página Standard. Al botón pon en su propiedad caption el texto Añadir. Algo así como la imagen adjunta. Y en el evento OnClick del botón colocaremos un código como el que sigue:

procedure TForm1.Button1Click(Sender:TObject);
begin

      If Edit1.Text <> '' Then
       ListBox1.Items.Add (Edit1.Text);
end; 
end.

Si quieres saber cuantos elementos hay en tu lista, solo hay que preguntarlo. Sería una cosa así:
NumeroDeElementos : = ListBox1.Items.Count;

Fijate que devuelve un entero por lo tanto la variable debe de ser del tipo Integer.

Si observas detenidamente los dos ejemplos anteriores, te darás cuenta que los métodos que he usado son Add, y Count, y que el resto es común. Esto es porque el componente se llama ListBox1, y tiene entre sus propiedades una llamada Items, la cual es del tipo TString, y es la que puede manejar la lista, así por lo tanto las operaciones se deben aplicar a esa propiedad. En el caso de componente Memo la propiedad que es del tipo TString se llama Lines, entonces la operación para obtener el número de elementos que tiene un componente de este tipo seria como sigue:
NúmeroDeElementos : = Memo1.Lines.Count;

Para añadir un elemento en una posición determinada se usa el método Insert, un ejemplo:
ListBox1.Items.Insert (2,'Tercer Elemento');

Con este ejemplo añado un elemento a la tercera posición. Si he dicho tercera posición, no es un error, ya que el primer elemento es el número cero. Por eso en el capítulo anterior para imprimir en contenido del Memo, usaba un bucle desde cero hasta el número de líneas menos una, ya esta última propiedad devuelve el número de elementos contados desde uno.

Si quieres mover un elemento usa el método move, así:
ListBox1.Items.Move (2,4);

Siendo su formato Origen, Destino, el ejemplo nueve el elemento tercero a la posición quinta.

Antes comente que TString era algo así como una Matriz, pues si es "como" una matriz accedamos a sus elementos por la posoción que ocupa, teniendo en cuenta que el primer elemento tiene como indice en número cero. Por ejemplo:
Label1.Caption := ListBox1.Items [2];

Este ejemplo copia el tercer elemento a una etiqueta.

Por ahora ha sido facil, pero para borrar un elemento debemos saber cual es su posiciónl, así estas líneas de código lo hacen. Primero comprobamos si existe el elemento (cuidado que distingue mayúsculas de minúsculas), en el caso que no exista devuelve -1, sino devuelve su posición. Si existe procedemos a borrarlo.
If ListBox1.Items.IndexOf ('jorge') > -1 Then
Delete (ListBox1.Items.IndexOf ('jorge');

Con este sistema podemos borrar un elemento, pero si deseamos borrar toda la lista, usamos el método Clear. Ejemplo:
ListBox1.Items.Clear;

En algún momento te encontraras que necesitas copiar todos los elementos de una lista a otra. La solución podria ser leer todos los elementos de uno en uno, y grabarlos en la otra lista, por medio de un bucle. Pero lo más eficaz es copiar la lista entera de una operación. Por ejemplo:
ListBox2.Items := ListBox1.Items;

Antes os he comentado que cuando buscas un elemento debes tener cuidado con las mayúsculas y las minúsculas, aqui os muestro un procedimiento que yo uso con frecuencia para buscar un elemento en una lista sin tener en cuenta las mayúsculas o las minúsculas:
For I := 0 to ListBox1.Items.Count -1 Do
Begin
If upcase (Micadena) = upcase(listBox1.Items[i] Then
ShowMesage ('Lo he encontrado');
End;

Quizas alguien este pensando que esto todo está bien, pero si trabajo con una lista y luego no puedo guardarla para usarla más tarde, pues apaga y vamonos. Pues si recordais el capítulo sobre el editor de texto, vereís que en componente Memo tiene un método para guardar y cargar texto, pero si te fijas es un método que se aplica a la propiedad Lines, la cual es un TString, a lo que me lleva que la "abilidad" para cargar/guardar texto no es caracteristico del componente sino que es heredado del objeto TString. Así una lista se puede cargar/guardar de la misma manera:
ListBox1.Items.LoadFromFile ('MiLista.txt'); //Para cargar
ListBox1.Items.SaveToFile ('MiLista'); //Para guardar

Listas en Memoria.

Todos los ejemplos que he puesto se basan en un componente visual, pero yo he comentado que la listas pueden ser internas. Así que para crear una lista en memoria debemos crear el objeto nosotros. así:
MiLista := TStringList.Create;

En cuanto crees la lista todo los métodos anteriores son aplicables normalmente. Por ejemplo:
MiLista.Add ('Mi elemento');

No te olvides de destruir la lista de la memoria cuando no la necesites:
MiLista.Free;

Por cierto, cuando crees la lista, esta se comporta como una variable en lo que respecta a ambito de variables. Osea que se declaras la variable en un procedimiento, solo podras usar esa lista en ese procedimiento, si la declaras a nivel Privado (Private) la podras usar en toda la unidad. Un ejemplo de una lista que se puede usar en toda una unidad:

unit feo;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    MiLista : TStringList;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
 MiLista := TStringList.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     MiLista.Free;
end;

end.