Newsgroup: it.comp.lang.delphi
Titolo: Utilizzare una lista di liste !!

ciao a tutti, ho questo problema:
ho creato una TList in cui vado ad inserire puntatori a dei record che
contengono a loro volta una lista in cui inserire puntatori ad un altro tipo
di record...
mi spiego meglio facendovi vedere il codice della dichiarazione di tipo:
type
   TPolylist =record
            x1:integer;
            x2:integer;
            y1:integer;
            y2:integer;
            a:boolean;
         end;
   TPianiList = record
                nome:string;
                numero:integer;
                List_Obj:TList;
                  end;
    PPolyList=^TPolyList;
    PPianiList=^TPianiList;
var
AObj:PPolyList;
  ALay:PPianiList;
Nella procedura della creazione della form ho inserito:
List_Lay:=TList.create;
Poi ho implementato una procedura cosě che mi crea un record di tipo
TPianiList e lo aggiunge alla List_Lay ed inoltre crea una istanza della
lista List_Obj...
Procedure Vattelappesca(.........)
begin
     new(ALay);
     ALay^.nome:=nome;
     ALay^.numero:=numero;
     ALay^.List_Obj:=TList.create;
     List_Lay.add(ALay);
     dispose(ALay);
end;
ed un'altra procedura cosi':
Procedure TForm1.Salva_Piano(nome_piano:string;id:integer;poli:Trect);
begin
  new(AObj);
  Aobj^.piano:=nome_piano;
  Aobj^.id:=id;
  ....
  .... vengono assegnati tutti i valori ai campi di Aobj.
List_Lay.items[num_piano_sel(nome_piano)]^.list_obj.add(AObj);
questa riga mi da errore nella compilazione (record,object, or class type
required).La riga deve aggiungere questo Aobj alla lista che fa parte
dell'elemento di List_Lay che ritorna dalla funzione num_piano_sel. Perň c'č
qualcosa che non quadra...sapete aiutarmi ?
dispose(Aobj);
end;
PS : Ma i TList possono contenere puntatori anche a tipi differenti ? Cioč
posso metterci dentro puntatori a interi, stringhe e record
contemporaneamente ?
Grazie
Daniele

>
PS : Ma i TList possono contenere puntatori anche a tipi differenti ? Cioè
posso metterci dentro puntatori a interi, stringhe e record
contemporaneamente ?
<<
mah, io direi di sì (mai provato però), in fondo una tlist non
è "nient'altro" che una lista di puntatori, e i puntatori
sono sempre di 4 byte, indifferentemente dal tipo a cui puntano
Ciao
Alan
---
Questo servizio e' realizzato con Wappi della Virtex
Connetti ad internet il tuo telefonino: 
http://www.wappi.com/
--
Posted from [194.243.91.36] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

contemporaneamente ?
Naturalmente..
Ciao,
-=SIMO=-

 Prova a fare il casting a TList, dovrebbe andare...
scusa l'ignoranza, cosa intendi con fare il cast?
(e soprattutto xchè bisogna farlo?)
scusa anche per la posizione del post
Ciao e grazie


(e soprattutto xchè bisogna farlo?)
List_Lay.Items[Num_Piano_Sel(Nome_Piano)] è un puntatore non tipizzato..
Infatti il metodo Add di TList è definito come segue:
function Add(Item: Pointer): Integer;
Quindi quando si usa Add(Ptr) il puntatore viene convertito a Pointer,
perdendo l'informazione sul tipo.
Per restituire l'informazione sul tipo al compilatore occorre effettuare il
casting, ovvero indicare il tipo del contenuto del puntatore..
In pratica :
TPianiList(List_Lay.Items[Num_Piano_Sel(Nome_Piano)]^).List_Obj.Add(AObj);
Lo stesso effetto può essere ottenuto assegnando il contenuto del
puntatore ad una variabile di appoggio.
In questo modo il compilatore effettua un casting implicito al tipo della
variabile di appoggio :
var
  Pippo: TPianiList;
Pippo:= List_Lay.Items[Num_Piano_Sel(Nome_Piano)]^;
Pippo.List_Obj.Add(AObj);
Comunque nel codice c'è un altro errore:
Procedure Vattelappesca(.........)
begin
     new(ALay);
     ALay^.nome:=nome;
     ALay^.numero:=numero;
     ALay^.List_Obj:=TList.create;
     List_Lay.add(ALay);
     dispose(ALay);  // <<<<<--- ERRORE !!
end;
Infatti ALay, dopo essere stato aggiunto alla lista di puntatori, viene
deallocato..
A questo punto il puntatore contenuto nella lista è NON VALIDO..
E' sufficiente eliminare il Dispose e deallocare solo quando si è sicuri che
il puntatore non verrà più utilizzato..
Ciao,
-=SIMO=-

sono sempre di 4 byte, indifferentemente dal tipo a cui puntano
Sotto Windows e' cosi', ma non e' vero sempre.
La dimensione delle variabili varia in base al tipo e due puntatori
che puntano a tipi di dati differenti SONO due tipi di dati differenti
e quindi potrebbero avere dimensioni distinte.
Ci sono sistemi in cui i puntatori a caratteri e i puntatori a interi,
per esempio, hanno dimensioni differenti.
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------
#exclude <windows.h>

contemporaneamente ?
Si', ma non e' consigliabile.
Meglio, in caso di necessita', utilizzare un record con un case
interno (quello che in C e' una "union", per intenderci).
Mi sono permesso di riscriverti il programma corretto :
program ListaDiListe ;
{$APPTYPE CONSOLE}
{(C) 2000 Andrea Laforgia}
uses SysUtils, Classes ;
type TPolyListRecord = record
                         iDato : integer ;
                       end ;
     PPolyListRecord = ^TPolyListRecord ;
type TPlanesList = record
                     strName : string ;
                     iNum : integer ;
                     lstSubList : TList ;
                   end ;
     PPlanesList = ^TPlanesList ;
var Lista : PPlanesList ;
function CreateANewRecord( X : integer ) : PPolyListRecord ;
var P : PPolyListRecord ;
begin
  GetMem( P, SizeOf( P^ ) ) ;
  P^.iDato := X ;
  Result := P ;
end ;
procedure AddANewPlane( var Head : PPlanesList ;
                            P : PPolyListRecord ) ;
begin
  if ( Assigned( Head ) ) then
  begin
    if ( not Assigned( Head.lstSubList ) ) then
      Head.lstSubList := TList.Create ;
    Head.lstSubList.Add( P ) ;
    Inc( Head.iNum ) ;
  end ;
end ;
procedure WriteList( Head : PPlanesList ) ;
var I : integer ;
begin
  writeln( 'The list name is : ' + Head^.strName ) ;
  writeln( 'The number of elements is : ', Head^.iNum ) ;
  for I := 0 to Head.lstSubList.Count-1 do
    writeln( 'Element[',I,'] = ', integer(Head.lstSubList.Items[I]^) )
;
end ;
procedure DestroyList( var Head : PPlanesList ) ;
var I : integer ;
begin
  if ( Assigned( Head ) ) then
  begin
    for I := 0 to Head^.lstSubList.Count - 1 do
      FreeMem( Head^.lstSubList[I] ) ;
    FreeMem( Head ) ;
    Head := NIL ;
  end ;
end ;
begin
  GetMem( Lista, SizeOf( Lista^ ) ) ;
  Lista^.iNum := 0 ;
  Lista^.lstSubList := NIL ;
  Lista.strName := 'MiaLista di Prova' ;
  AddANewPlane( Lista, CreateANewRecord( 2 ) ) ;
  AddANewPlane( Lista, CreateANewRecord( -1 ) ) ;
  AddANewPlane( Lista, CreateANewRecord( 3 ) ) ;
  WriteList( Lista ) ;
  DestroyList( Lista ) ;
end.


Si', ma non e' consigliabile.
Perchè ?
Secondo me questo permette una maggiore flessibilità se si usa il TList con
puntatori ad oggetti..
Ciao,
-=SIMO=-

puntatori ad oggetti..
Ad oggetti e' un conto, a strutture dati classiche e' un altro conto.
Per gli oggetti e' possibile sfruttare i comportamenti polimorfici,
per le strutture dati classiche no. Dato che bisognerebbe comunque
avere nella memoria puntata, un riferimento al *tipo* di oggetto
puntato, la soluzione migliore puo' essere quella di implementare un
record con una scelta "case" tra i vari tipi supportati.


 TPianiList(List_Lay.Items[Num_Piano_Sel(Nome_Piano)]^).List_Obj.Add(AObj);
Grazie -=SIMO=-, ora ho capito.
E io che mi ero già convinto che fosse un bug del compilatore.
Adesso mi è chiaro anche il messaggio di errore
"record,object, or class type required"
traduzione-> "a cosa cavolo punta questo puntatore?"
per la serie bastava leggere...
Grazie di nuovo
Ciao
Alan Solo
ps [OT]: finalmente non devo scrivere da web, funziona tutto alla grande!!
Libero per spedire, Wappi per ricevereeeeeee(SBONK!...scusate questo momento
di esaltazione)
... ah dimementicavo, anche nuovo nick (star wars rulez!) :-)
bye

 #exclude <windows.h>
bwahahah :-)))) bellissima!!
Ciao
Alan Solo

puntare...o no?
Questa e' una certezza su molti sistemi a 64 bit. 
Ripeto : puntatori a tipi differenti SONO a tutti gli effetti tipi
differenti e quindi potrebbero avere dimensioni differenti.
Sotto Windows, tuttavia, non e' cosi'.
