Dificuldade com TList

Delphi

14/09/2007

Olá pessoal,
estou tentado fazer um exemplo conforme mostrado abaixo com o TList.

Defini uma classe a titulo de exemplo chamada TPessoa conforme o código abaixo:

  TPessoa = class
  public
    Chave : integer;
    Nome : string;
    Data : tDate;
  end;


Minha idéia e colocar uma lista de pessoas no TList :shock: . Até ai sem problemas defini uma variável do tipo TList chamada Lista e criei ela no evento OnCreate do Form. No OnDestroy do form libero ela.


Lista : TList;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Lista := TList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Lista.Free;
end;


Defini um procedimento para inserir pessoas na lista. Esse procedimento cria uma objeto do tipo TPessoa atribui valores a ele e inseri na lista como pode ser observado no código abaixo:



procedure TForm1.InseriPessoaLista(Chave : integer; Nome : string; DataNascimento : TDate);
var
 P : TPessoa;
begin
  P := TPessoa.Create;
  P.Nome  := Nome;
  P.Data  := DataNascimento
  P.Chave := Chave

  //Adicionando na lista

  Lista.Add(P);

//DEVO OU NÃO DEVO LIBERAR O OBJETO P?
//  P.Free;
end;


Minha primeira dúvida: :oops:

:arrow: P.Free;

Como foi definido uma variável do tipo TPessoa dentro da função InseriPessoaLista devo liberar ela ao finalizar o procediemento? Se fizer isso consigo ler os dados da pessoa ao percorrer a lista? :oops:

Feito esse procedimento criei um outro para ler as informações da lista conforme pode ser visto na listagem abaixo:

procedure TForm1.LeLista();
begin
  for i:=0 to Lista.Count-1 do
  begin
    ListaBox1.Items.Add(FormatFloat(´00´, TPessoa(Lista.Items[i]).Chave+´ - ´+TPessoa(Lista.Items[i]).Nome + ´ - ´ +FormatDateTime(´dd/mm/yyyy´, TPessoa(Lista.Items[i]).Data);
  end;
end;

Esse procedimento é executado sem problemas quando o obejto TPessoa da função ´InseriPessoaLista´ não é liberado. Se ele é liberado ´P.Free´ ocorre erro ao executar o procedimento ´LeLista´.

Após isso definir um procedimento para retornar uma pessoa definida uma determinada chave. A minha idéia é passar o valor da chave e ter como retorno da função um objeto do tipo TPessoa.

Estou TENTANDO mas não estou conseguido:


function TForm1.RetornaPessoa(chave : integer) : TPessoa
var
  i : integer;
begin
  Result := nil;
  for i:=0 to Lista.Count-1 do
  begin
    if TPessoa(Lista.Items[i]).Chave = Chave then
    begin
      result := TPessoa(Lista.Items[i]));
      break;
    end;
  end;
end;



EXISTE alguma forma mais [b:3129382b01]inteligente[/b:3129382b01] de localizar a pessoa na lista?

Por enquanto é isso....


Carlosib

Carlosib

Curtidas 0

Respostas

Carlosib

Carlosib

14/09/2007

Sobe :oops:


GOSTEI 0
Jessedelsole

Jessedelsole

14/09/2007

Olá carlos

A classe TList, guarda apenas uma referência de algum objeto. A referência seria um ponteiro de memória, apenas um número inteiro. Ou seja, se você liberar o objeto pessoa, depois a lista não vai mais conseguir encontrá-la.

Quanto a maneira que você utilizou para localizar o cliente pelo código, achei q ficou legal. Porém, outra maneira de se fazer isso seria criar um array dinâmico de TPessoa, que dispensaria o uso da lista, deixando teoricamente o programa mais leve :


//variavel global
Pessoas : array of TPessoa




Quando vou inserir um cliente, vou redimensionando o array conforme a demanda :

procedure TForm1.insereCliente(nome: string; chave: integer);
begin
   SetLength(Pessoas,high(Pessoas)+2);
   Pessoas[high(Pessoas)] := TPessoa.Create;
   Pessoas[high(Pessoas)].Nome := nome;
   Pessoas[high(Pessoas)].chave := chave;
end;


Aqui é a função para retornar a [b:10bb86cf45]referência[/b:10bb86cf45] do cliente requisitado.

function TForm1.RetornaPessoa(chave: integer): Tpessoa;
var i:integer;
begin
    result := nil;
    for i := low(Pessoas) to high(Pessoas) do
    if Pessoas[i].chave = chave then
    begin
         result := Pessoas[i];
         break;
    end;
end;



caso queira retornar um novo objeto de pessoa para o cliente requisitado, a função ficaria assim :

function TForm1.retornaObjetoDePessoa(chave: integer): TPessoa;
var i : integer;
begin
    result := nil;

    for i := low(Pessoas) to high(Pessoas) do
    if Pessoas[i].chave = chave then
    begin
         result := TPessoa.Create;
         result.Nome := pessoas[i].Nome;
         result.chave := pessoas[i].chave;
         break;
    end;
end;



Aqui irei adicionar as pessoas num listBox

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
  for i := Low(Pessoas) to high(Pessoas) do
  listbox1.Items.Add(Pessoas[i].Nome);
end;



Por último estou liberando todos as pessoas instanciadas :

procedure TForm1.FormDestroy(Sender: TObject);
var i : integer;
begin
   for i := high(pessoas) downto low(Pessoas) do
    FreeAndNil(Pessoas[i]);
end;



Espero ter ajudado em alguma coisa


GOSTEI 0
Carlosib

Carlosib

14/09/2007

Olá amigo,
obrigado pela resposta.

1) Já uso array dinâmico. Porém achava que com TList ou outro ´derivado´ teria mais ´facilidades´.

2) porque você usa FreeAndNil(Pessoas[i]) ao invés de Pessoas[i].Free?

Qual seria a diferença entre eles?


GOSTEI 0
Rinez

Rinez

14/09/2007

Prezado colega:
Voce pode usar clientedataset da paleta Data Acess
Um exemplo para voce testar, quando a perform eu não sei,
outros colegas poderão dar opinião.
As vezes uso no dropdown do combobox para carregar nome de arquivo texto em ordem decrescente:
Coloque em um form um clientedataset, 3 edits, um listbox e e botoes.
coloque o nome do clientdataset cdspessoas
Teste aí e nos responda o que achou.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, DB, DBClient;

type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
cdspessoas: TClientDataSet;
ListBox1: TListBox;
BitBtn3: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IF Cdspessoas.FieldCount=0 THEN BEGIN
with Cdspessoas do begin

with FieldDefs.AddFieldDef do
begin
DataType := ftInteger;
Name := ´Chave´;
end;

with FieldDefs.AddFieldDef do
begin
DataType := ftSTRING;
size:=400;
Name := ´PESSOA´;
end;

with FieldDefs.AddFieldDef do
begin
DataType := ftdate;

Name := ´DATA´;
end;

CreateDataSet;
end; //with cdpessoas do begin
end; //IF Cdpessoas.FieldCount=0 THEN BEGIN

CDSPESSOAS.EmptyDataSet; // limpacdsteste
showmessage(´ClientDataset Criado com sucesso´);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
cdspessoas.Close;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
var
i:integer;
mdata:tdate;
begin

try
i:=strtoint(edit1.Text);
except
on e: exception do begin
// on EConvertError do begin
showmessage(´erro número invádo´);
edit1.setfocus;
exit;
end; end;


try
mdata:=strtodate(edit3.Text);
except
on e: exception do begin
showmessage(´erro data inváda´);
edit3.setfocus;
exit;
end; end;

CDSPESSOAS.OPEN;
cdspessoas.Append;
cdspessoas.fieldbyname(´chave´).asinteger:=I;
cdspessoas.fieldbyname(´pessoa´).asstring:=EDIT2.TEXT;
cdspessoas.fieldbyname(´data´).value:=STRTODATE(EDIT3.Text);
CDSPESSOAS.Post;
LISTBOX1.Items.Add(cdspessoas.fieldbyname(´chave´).ASSTRING+´ - ´+cdspessoas.fieldbyname(´pessoa´).asstring+´ - ´+
cdspessoas.fieldbyname(´data´).ASSTRING);


end;

procedure TForm1.BitBtn3Click(Sender: TObject);
var
s:string;
begin
s:= InputBox(s, ´Entre com Numero a procurar´, ´´);

cdspessoaS.filtered := False;
cdspessoaS.filter := ´CHAVE = ´ + QuotedStr(S);
cdspessoas.Filtered := True;
SHOWMESSAGE(´CHAVE ´+CDSPESSOAS.FIELDBYNAME(´CHAVE´).AsString+
´Nome ´+CDSPESSOAS.FIELDBYNAME(´pessoa´).AsString);
end;

end.


GOSTEI 0
Jessedelsole

Jessedelsole

14/09/2007

Free libera o objeto da memória,
enquanto freeAndNil, além de liberar o objeto da memória, remove também o ponteiro do mesmo .


GOSTEI 0
POSTAR