Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Narciso - Settembre 13, 2016, 04:57:34 pm

Titolo: Implementare liste di tipi complessi...
Inserito da: Narciso - Settembre 13, 2016, 04:57:34 pm
Sto provando ad implementare una lista di oggetti per non avere le limitazioni degli array, ma mi sono infognato.
Ho letto il suggerimento nel sito, ma usa record e puntatori, io avrei usato una classe.

Posto un po' di codice...

***********
i miei tipi


type tdocente=record
     nome:string[255];
     attivo:boolean;
     orediservizio:integer;
     mingiorno:integer;
     maxgiorno:integer;
     quadrovincoli:array[0..6,0..10]of integer;
     end;
type tmateria=record
     id:string[255];
     colore:tcolor;
     attiva:boolean;
     end;
type tclasse=record
     attiva:boolean;
     id:string[255];
     quadrosettimana:array[0..6,0..10] of integer;
     end;


type
   tlezione=class
      materia:tmateria ;
      classe:tclasse;
      durata:integer;
      docente:tdocente;
      peso:integer;
      attiva:boolean;
     end;



  type torario=record
       nomeorario:string[255];
       giorniasettimana:integer;
       maxorealgiorno:integer;
       Uorariainminuti:integer;
       quadrosettimana:array[0..6,0..10] of integer;
       ndocenti:integer;
       nmaterie:integer;
       nclassi:integer;
       nlezioni:integer;
       docenti:array[0..100]of tdocente;
       materie:array[0..40] of tmateria;
       classi:array[0..100] of tclasse;
   

  end;             

*****************

quando vado ad assegnare i dati... mi da' errore

procedure TFormdatilezione.BitBtn4Click(Sender: TObject);
var
  obj:tlezione;
  x:integer;
begin
   obj.materia:=o.materie[combobox1.itemindex];<----errore eccezione di classe SGSERV.....
   obj.classe:=o.classi[combobox2.ItemIndex];
   obj.durata:=spinedit1.value;
   obj.docente:=o.docenti[combobox3.itemindex];
   obj.attiva:=checkbox1.checked;
   listalezioni.add(obj);
   memo1.clear;
   for x:= 0 to listalezioni.Count-1 do begin
   memo1.lines.add.... dovrei completare il codice;

   end;
Premetto che non ho usato mai le liste e anche con le classi faccio a cazzotti.... se qualcuno di buon cuore volesse aiutrami... mi servirebbe il modo per assegnare i dati di un form ad un oggetto tlezione...e magari acapire poi come accedervi e salvare i dati su file....

Grazie


end;     




Titolo: Re:Implementare liste di tipi complessi...
Inserito da: Stilgar - Settembre 13, 2016, 10:48:12 pm
Ciao Narciso.
Dal codice non capisco molto.
Puoi allegate tutto il file?

Ad intuito il problema sta
Codice: [Seleziona]
o.materie[combobox1.itemindex];

Stilgar
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: AndreaM - Settembre 14, 2016, 12:44:26 pm
Ciao,
Credo che il problema stia nel fatto che l'oggetto  obj:tlezione dichiarato in procedura, non è stato creato prima di essere utilizzato.
Prima della riga dove si blocca in errore, dovresti mettere:
obj:=TLezione.Create;
....
e poi lo usi come vuoi.
Prova, non ho lazarus sotto mano per verificare.
Saluti
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: Narciso - Settembre 20, 2016, 06:35:50 pm
ed avevi ragione
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: nomorelogic - Settembre 20, 2016, 06:55:40 pm
giusto per curiosità, vorrei chiederti di provare a compilare con l'opzione heaptrace (-gh come opzione o heaptrc come prima unit della clausola uses del progetto) e poi lanciare il .exe da una shell
fai pure creare la lista, quando chiudi l'applicazione, cosa compare nella shell?
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: nomorelogic - Settembre 20, 2016, 07:11:09 pm
Sto provando ad implementare una lista di oggetti per non avere le limitazioni degli array, ma mi sono infognato.
Ho letto il suggerimento nel sito, ma usa record e puntatori, io avrei usato una classe.
...
Premetto che non ho usato mai le liste e anche con le classi faccio a cazzotti.... se qualcuno di buon cuore volesse aiutrami... mi servirebbe il modo per assegnare i dati di un form ad un oggetto tlezione...e magari acapire poi come accedervi e salvare i dati su file....

nei tipi che hai dichiarato non vedo metodi, i record li vedrei più adatti

per leggere/scrivere da file puoi prendere spunto da quì
http://stackoverflow.com/questions/5763247/simple-read-write-record-dat-file-in-delphi (http://stackoverflow.com/questions/5763247/simple-read-write-record-dat-file-in-delphi)

se invece preferisci le classi, tramite RTTI puoi salvare su file quasi automaticamente, devi dichiarare le proprietà sotto *published*
esempio:
Codice: [Seleziona]
type
   tlezione=class
   private
      Fmateria: tmateria; // <- questa riga è gestita automaticamente con: Ctrl+Alt+C
   published
      ...
      property materia:tmateria read Fmateria write FMateria;
      ...
   end;



Titolo: Re:Implementare liste di tipi complessi...
Inserito da: renabor - Settembre 22, 2016, 08:32:47 am
Ciao Narciso,
tempo fa mi sono scontrato anch'io con le limitazioni degli array e alla fine ho trovato un modo estremanete semplice ed utile per implementare le SstringList.
Innanzitutto bisogna definire il type dell'oggetto base che associeremo alle StringList:
(in questo esempio creo una stringlist con associato un integer di nome indice e del testo)
Codice: [Seleziona]
type
   Tindice = class
   private
     fIndice: integer;
     fTesto : string;
   public
     property indice : integer read fIndice;
     property testo  : string read fTesto;
     constructor Create(const _indice : integer; const _testo:string);
   end; 
quindi creo la lista ed aggiungo alcuni elementi
Codice: [Seleziona]
lista=TStringList.Create;
lista.AddObject('prima riga della lista',TIndice.Create(12,'PRIMO ELEMENTO'));
lista.AddObject('seconda riga della lista',TIndice.Create(53,'SECONDO ELEMENTO'));
lista.AddObject('terza riga della lista',TIndice.Create(22,'TERZO ELEMENTO'));
se ora voglio accedere al contenuto di un elemento della lista, conoscendone l'index:
Codice: [Seleziona]
  writeln(inttostr(TIndice(lista.Objects[1]).indice));
  writeln(TIndice(lista.Objects[1]).testo);   
ed otterrò:
  53
  SECONDO ELEMENTO
se invece voglio cercare l'indice nella lista cui corrisponde un determinato testo uso questa funzione
Codice: [Seleziona]

function cerca_indice(Items:TStrings; testo_da_cercare:string):integer;
var n:integer;
    i:TIndice;
begin
  for n:=0 to Items.Count-1 do begin
    i := Items.Objects[n] as TIndice;
    if i.testo=testo_da_cercare then begin
      Result:=n;
      exit;
    end;
  end;
  Result:=-1;
end;
ad esempio:
  writeln(inttostr(cerca_indice(lista,'TERZO ELEMENTO')));
darà come risultato 2
e alla fine, per pulire tutto
Codice: [Seleziona]
  for i:=0 to lista.Count -1 do lista.Objects[i].Free;
  lista.Clear; 
Spero possa aiutarti!
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: Narciso - Settembre 23, 2016, 04:30:17 pm
ti ringrazio, ma evidentemente l'esempio delle stringlist non e' il piu' pregnante.... esistono già.... ma e' valido come esempio
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: bonmario - Settembre 23, 2016, 05:07:41 pm

e alla fine, per pulire tutto
Codice: [Seleziona]
  for i:=0 to lista.Count -1 do lista.Objects[i].Free;
  lista.Clear; 
Spero possa aiutarti!

Spero di non dire una cavolata, ma se non ho capito male, se fa questo:
Codice: [Seleziona]
lista.OwnsObjects:=True;

Poi può fare direttamente
Codice: [Seleziona]
      
Lista.Clear;


Ciao, Mario
Titolo: Re:Implementare liste di tipi complessi...
Inserito da: SB - Settembre 25, 2016, 11:19:39 am
Sto provando ad implementare una lista di oggetti per non avere le limitazioni degli array, ma mi sono infognato.
Ho letto il suggerimento nel sito, ma usa record e puntatori, io avrei usato una classe.
...
Premetto che non ho usato mai le liste e anche con le classi faccio a cazzotti.... se qualcuno di buon cuore volesse aiutrami... mi servirebbe il modo per assegnare i dati di un form ad un oggetto tlezione...e magari acapire poi come accedervi e salvare i dati su file....
end;     

Se ho capito cosa stai facendo, usa tranquillamente gli array di record come stavi tentando di fare.
Lascia perdere gli array dinamici, le classi e le liste che in questo caso non servono a niente.
Per leggere e scrivere valori non creare niente ma accedi direttamente all'elemento che ti serve.
Per salvataggio e lettura su file usa le funzioni che scrivono e leggono aree di memoria (buffer). Se usi array statici l'area di memoria della struttura complessiva dovrebbe essere contigua. Per la dimensione totale basta un sizeof() della struttura che racchiude tutto.

Se invece ci sono delle limitazioni agli array che ti impediscono di fare così, prova a dire quali sono queste limitazioni che forse ci sono strade migliori.

Titolo: Re:Implementare liste di tipi complessi...
Inserito da: renabor - Settembre 26, 2016, 06:35:53 pm

e alla fine, per pulire tutto
Codice: [Seleziona]
  for i:=0 to lista.Count -1 do lista.Objects[i].Free;
  lista.Clear; 
Spero possa aiutarti!

Spero di non dire una cavolata, ma se non ho capito male, se fa questo:
Codice: [Seleziona]
lista.OwnsObjects:=True;

Poi può fare direttamente
Codice: [Seleziona]
      
Lista.Clear;


Ciao, Mario

Hai ragione, è possibile usare anche questo metodo più semplice e anche molto più elegante. Verificato e la memoria alla fine viene liberata completamente in tutti e due i modi
grazie
ciao Renabor