Telefonino.net network
 
| HOMEPAGE | INDICE FORUM | REGOLAMENTO | ::. NEI PREFERITI .:: | RSS Forum | RSS News | NEWS web | NEWS software |
| PUBBLICITA' | | ARTICOLI | WIN XP | VISTA | WIN 7 | REGISTRI | SOFTWARE | MANUALI | RECENSIONI | LINUX | HUMOR | HARDWARE | DOWNLOAD | | CERCA nel FORUM » |

Torna indietro   WinTricks Forum > Software > Programmazione

Notices

Rispondi
 
Strumenti discussione
Vecchio 02-09-2009, 15.02.06   #1
leuconoe
Newbie
 
Registrato: 24-08-2009
Messaggi: 4
leuconoe promette bene
[C++] Lista di struct

Salve gente
sto lavorando ad un progetto con linguaggio c++.
Mi è stato chiesto di implementare un template lista basato su un template elemento di lista utilizzando 2 campi generici e i vari puntatori che servono per implementare le liste.
Poi dovrei utilizzare il template lista per costruire una biblioteca.
in questa biblioteca si utlizza la struct Infovolume con vari campi che danno informazioni sul volume.
Quindi credo che debba implementare una lista di struct Infovolume per costruire la classe biblioteca.
Ecco la domanda è:
è possibile usare le funzioni base della lista oppure devo ricostruire ogni funzione per la nuova classe biblioteca?
Cioè ad esempio: per inserire il nome del volume, devo richiamare la funzione inserisci del template lista oppure costruirne un'altra nella classe biblioteca? e se si, che tipo di sintassi bisogna usare?

Scusate le domande ma sul manuale ho semplici esempi di classi che utilizzano come tipo di dato nel template un dato semplice come intero oppure striung. Non so come comportarmi con liste di struct.
Grazie mille

Codice:
//dichiarazione del template elemento di lista
template<class gen> class List_element {
public:
  gen data;
  gen key;
  List_element<gen> *succ;
  List_element<gen> *prec;
  
         List_element();
         ~List_element();
         void set_element(gen a,gen b);
         gen get_element();
         List_element *get_next();
         void set_next(List_element *p);
         List_element *get_prev();
         void set_prev(List_element *s);

//dichiarazione del template lista bidirezionale
template <class gen> class lista_concatenata_bidirezionale {
   
  public: List_element<gen>* TestaDiLista;  
   List_element<gen>* CodaDiLista; 
   int num_elementi; 

   
         lista_concatenata_bidirezionale();
         ~lista_concatenata_bidirezionale();
         void Crea_lista();
         bool Lista_vuota();
         List_element<gen>* ultimo_lista(); 
         gen  leggi(List_element<gen>*p);
         void scrivi(List_element<gen>*p, gen a,gen b);
         void cancella(List_element<gen>*p);
         void inserisci(List_element<gen>*p, gen a,gen b);
         int  getNumElementi();
         List_element<gen>* cerca(gen a);
         void Stampa_lista();
         List_element<gen>* succ_lista(List_element<gen>* pos);
};

//dichiarazione di Infovolume
struct Infovolume
{
    string nome;
   string disposizione;
   int disponibilita';
}

//dichiarazione di Biblioteca
class Biblioteca
{
   lista_concatenata_bidirezionale<Infovolume> biblioteca;
   
   .......................................................
............................................................
..........................................................
};
leuconoe non è collegato   Rispondi citando
Vecchio 02-09-2009, 16.53.12   #2
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
Se la lista è specializzata (ovvero non opera con tipi nativi) e devi reimplementare il suo template occorre specializzare anche i metodi che consento di : inserire (push_back) cancellare (remove, removeat opzionale) e iterare (iteratore) poiché operino con l'oggetto struttura o con l'operatore di cui hai bisogno

guarda qui per l'implementazione standard di una lista
http://www.ziggyware.com/readarticle.php?article_id=20

prendi spunto da questo esempio e reimplementa il tuo template poiché sia in grado di operare con la struct di cui hai bisogno, reimplementa soltanto i metodi che ti servono dopodiché usala come una normale lista

Codice:
listtemplate <InfoVolume> myList ...
utilizzando i metodi implementati per gestirla.

Ultima modifica di P8257 WebMaster : 02-09-2009 alle ore 17.24.21
P8257 WebMaster non è collegato   Rispondi citando
Vecchio 03-09-2009, 19.24.38   #3
leuconoe
Newbie
 
Registrato: 24-08-2009
Messaggi: 4
leuconoe promette bene
Ciao WebMaster e grazie per il consiglio. In realtà ho già implementato sia il template lista che il template elemento di lista come nell'esempio.
Il problema è che non riesco ad operare sui singoli campi della struct utilizzando le funzioni base che operano su tipi generici implementate nei template.
cioè come faccio ad aggiornare ad esempio la quantità di un libro con le sole operazioni definite nel template?
leuconoe non è collegato   Rispondi citando
Vecchio 03-09-2009, 23.24.11   #4
LoryOne
Gold Member
WT Expert
 
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.502
LoryOne è un gioiello raroLoryOne è un gioiello raroLoryOne è un gioiello raro
Codice semplice per i semplici concetti fondamentali...
Funzioni generiche

Codice:
/* swapargs è una funzione generica alla quale vengono passati
   due parametri di tipo X. X non ha nulla a che vedere con la classe.
   Ad X verrà assegnata la tipologia del dato nel momento in cui verrà
   invocata la funzione swapargs.
*/
template <class X> void swapargs(X &a, X &b){ 
  /* A swapargs vengono passati gli indirizzi di a e b il cui valore dipenderà
     dal tipo del dato specificato al momento della compilazione del codice. 
  */
  X temp; // temp è una variabile temporanea di tipo X.
          // Il tipo di dato referente ad a e b sarà specificato 
          // al momento della chiamata alla funzione swapargs.
  
  temp = a;
  a = b;
  b = temp;
  cout << "\nvalore di parametro1:" << a 
       << " valore di prametro2:" << b << "\n";
}; 
 
int main(void){ 
  // swapargs è sempre la stessa funzione, ma il tipo del parametro cambia.
  int i=10;
  int j=20;
  cout << "valore di parametro1:" << i 
       << " valore di parametro2:" << j;
  swapargs(i,j);  
  
  char c='a';
  char d='b';
  cout << "valore di parametro1:" << c 
       << " valore di parametro2:" << d;
  swapargs(c,d); 
  
  return 0;
}
Classi generiche

Codice:
/* MyClass è una classe generica alla quale vengono passati
   due parametri di tipo X. X non ha nulla a che vedere con la classe.
   Ad X verrà assegnata la tipologia del dato nel momento in cui verrà
   creato il costruttore di MyClass.
*/
template <class X> class MyClass{ 
  X x,y; //x ed y sono due variabili private generiche di tipo X
public:
  // Costruttore della classe MyClass    
  MyClass(X a, X b){ // a e b sono due variabili generiche di tipo X
    x = a;
    y = b;  
  }       
  // div() è una funzione generica della classe MyClass di tipo X
  X div(){ return x/y; }   
}; 
 
int main(void){ 
  /* d_ob è una classe generica che eredita da MyClass membri e funzioni il 
     cui tipo è specificato all atto del creazione del costruttore della classe  
  */
  MyClass<double> d_ob(10.0, 3.0);
  cout << "divisione di double: " << d_ob.div();
  
  /* i_ob è una classe generica che eredita da MyClass membri e funzioni il 
     cui tipo è specificato all atto del creazione del costruttore della classe  
  */
  MyClass<int> i_ob(10, 3);
  cout << "\ndivisione di interi: " << i_ob.div();
  return 0;
}
Classi specializzate

Codice:
/* MyClass è una classe generica alla quale vengono passati
   due parametri di tipo X. X non ha nulla a che vedere con la classe.
   Ad X verrà assegnata la tipologia del dato nel momento in cui verrà
   creato il costruttore di MyClass.
*/
template <class X> class MyClass{ 
  X x,y; //x ed y sono due variabili private generiche di tipo X
public:
  // Costruttore della classe generica MyClass    
  MyClass(X a, X b){ // a e b sono due variabili generiche di tipo X
    x = a;
    y = b;  
  }       
  // div() è una funzione generica della classe MyClass di tipo X
  X div(){ return x/y; }   
}; 

// I parametri passati a MyClass vengono definiti in modo specifico,  
template <> class MyClass<int>{ 
   int x, y; // x ed y sono due variabili private all'interno della classe
public:
   // Costruttore della classe specifica MyClass          
   MyClass(int a,int b){
    x = a;
    y = b;
 }       
 // div() è una funzione della classe MyClass di tipo intero.
 int div(){ return x/y; }   
};        
 
int main(void){ 
  /* d_ob è una classe generica che eredita da MyClass membri e funzioni il 
     cui tipo è specificato all atto del creazione del costruttore della classe  
  */
  MyClass<double> d_ob(10.0, 3.0);
  cout << "divisione di double: " << d_ob.div();
  
  /* i_ob è una classe generica che eredita da MyClass membri e funzioni il 
     cui tipo è specificato all atto del creazione del costruttore della classe  
  */
  MyClass<int> i_ob(10, 3);
  cout << "\ndivisione di interi: " << i_ob.div();
  return 0;
}
LoryOne non è collegato   Rispondi citando
Vecchio 04-09-2009, 00.12.21   #5
LoryOne
Gold Member
WT Expert
 
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.502
LoryOne è un gioiello raroLoryOne è un gioiello raroLoryOne è un gioiello raro
Ok, ora abbiamo gettato le basi per cominciare a comprendere la classe List http://www.cplusplus.com/reference/stl/list/
LoryOne non è collegato   Rispondi citando
Vecchio 04-09-2009, 10.24.40   #6
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
Non sono sicuro di aver capito bene il problema dell'operare coi campi, forse perché stai cercando di operare con una lista despecializzata su un contesto specializzato...

Oltre ai link e agli spunti che ti ha fornito Lory volevo suggerirti di guardare nuovamente il link dell'implementazione standard ed in particolare...

Codice:
        void push_back(T Item)
        {
            bValid=false;

            if(m_pEnd)
            {
                m_pEnd->m_pNext = new ListNode(Item);
                m_pEnd->m_pNext->m_pPrev = m_pEnd;
                m_pEnd = m_pEnd->m_pNext;
            }
            else
            {
                m_pHead = new ListNode(Item);
                m_pEnd = m_pHead;
            }
            m_dwSize++;
        }

        void Insert(T Item,ListNode* pPrev = 0)
        {
            bValid=false;
            m_dwSize++;

            if(!pPrev)
            {
                ListNode* pBase = m_pHead;
                m_pHead = new ListNode(Item);
                m_pHead->m_pNext = pBase;
                if(!pBase)
                    pBase = m_pHead;
                pBase->m_pPrev = m_pHead;
                if(!m_pEnd)
                {
                    m_pEnd = pBase;
                }
            }
            else
            {
                ListNode* pNext = pPrev->m_pNext;
                if(!pNext)
                {
                    pPrev->m_pNext = new ListNode(Item);
                    pPrev->m_pNext->m_pPrev = pPrev;
                    if(m_pEnd == pPrev)
                    {
                        m_pEnd = pPrev->m_pNext;
                    }
                }
                else
                {
                    pPrev->m_pNext = new ListNode(Item);
                    pPrev->m_pNext->m_pPrev = pPrev;
                    pPrev->m_pNext->m_pNext = pNext;
                    pNext->m_pPrev = pPrev->m_pNext;
                    if(m_pEnd == pPrev)
                    {
                        m_pEnd = pPrev->m_pNext;
                    }
                }
            }
        }
Come vedi, se la tua lista, al posto di essere generica fosse specifica (come in realtà dovrebbe essere) il problema dell'operare coi singoli campi non ce l'hai perché operi sul puntatore all'elemento listNode che nel tuo caso è l'intera struttura InfoVolume, ne consegue che per "aggiornare" la quantità di un certo volume in lista, a meno che non vuoi implementarti un metodo Update (ma il gioco non vale la candela) devi estrarre l'item dalla lista, crearne un'istanza per referenza, modificare il valore dei capmi di struttura, rimuoverlo dalla lista e riaggiungerlo, a tale scopo usa il metodo RemoveAt e Push_back...
P8257 WebMaster non è collegato   Rispondi citando
Vecchio 06-09-2009, 12.10.55   #7
LoryOne
Gold Member
WT Expert
 
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.502
LoryOne è un gioiello raroLoryOne è un gioiello raroLoryOne è un gioiello raro
Abbiamo visto che l'operatore new viene utilizzato per allocare ed eventualmente popolare un array di qualsiasi tipo attraverso l'utilizzo di un puntatore alla memoria dinamica (heap).
La classe generica list, utilizzabile attraverso l'inclusione dell'header <list.h> (#include <list>), fa ampio uso di template e di strutture che puntano a loro stesse, in modo tale da creare un array espandibile (dinamico) di oggetti.
Il link da me proposto, mostra come utilizzare la classe list in modo da creare un array di interi, ma non è molto chiaro su come gestire un array di strutture.
Una struttura è anch'essa un tipo di dato, così come lo sono int e char (persino una classe), ma può essere costituita da differenti tipi di dato, nonchè funzioni inline.

Facciamo un esempio semplice e chiaro:

1 - Creiamo la struttura MiaStruct1
struct MiaStruct1{
char x;
int y;
};

2 - Creiamo ora una classe list di tipo MiaStruct1
list<MiaStruct1> L1;

3 - Identifichiamo un puntatore alla struttura MiaStruct1
MiaStruct1 *p;

4 - Utilizziamo la classe L1 per allocare un array dinamico di 3 elementi di tipo MiaStruct1
p=L1.get_allocator().allocate(3);
p ora punta ad una lista concatenata di tre elementi di struttura MiaStruct1

5 - Popoliamo ogni elemento dell'array.
p[0].x='A' ; p[0].y=1 ;
p[1].x='B' ; p[1].y=2 ;
p[2].x='C' ; p[2].y=3 ;

6 - Visualizziamo ogni elemento dell'array
for(int i=0; i<3; i++) cout << p[i].x << p[i].y << endl;

7 - Infine deallochiamo la memoria dinamica allocata in precedenza.
L1.get_allocator().deallocate(p,3);

Vediamo ora un ulteriore esempio di utilizzo della classe facendo riferimento ai membri pubblici esplicitamente predisposti, al fine di ottenere un approccio più C++ alla classe list.

Facciamo un esempio semplice e chiaro:
1 - Creiamo la struttura MiaStruct2
struct MiaStruct2{
char x_;
int y_;
MiaStruct2(char x, int y) : x_(x), y_(y) { };
};
In questo caso, MiaStruct2 diventa una sorta di costruttore inline di se stessa che contiene al suo interno il prototipo.
si potrà popolare MiaStruct2 chiamandola direttamente ed assegnando ad x_ il valore di x ed ad y_ il valore di y.

2 - Creiamo ora una classe list di tipo MiaStruct2
list<MiaStruct2> L2;

4 - Utilizziamo la classe L2 per allocare un array dinamico di 3 elementi di tipo MiaStruct2
L2.push_back(MiaStruct2('a',1));
L2.push_back(MiaStruct2('b',2));
L2.push_back(MiaStruct2('c',3));

5 - Ora è necessario implementare un puntatore ad ogni elemento dell'array, in modo da poter iterare su ogni elemento di cui si compone l'insieme.
list<MiaStruct2>::iterator it2;

6 - Visualizziamo ogni elemento dell'array
for(it2=L2.begin(); it2!=L2.end(); it2++) cout << (*it2).x_ << (*it2).y_ << endl;

In ultimo, il programma completo:

Codice:
struct MiaStruct1{
    char x;
    int y;
};

struct MiaStruct2{
    char x_;
    int y_;
    MiaStruct2(char x, int y) : x_(x), y_(y) { };
};

main(void){

    list<MiaStruct1> L1;
    MiaStruct1 *p;
   
    p=L1.get_allocator().allocate(3);
    p[0].x='A' ; p[0].y=1 ;
    p[1].x='B' ; p[1].y=2 ;
    p[2].x='C' ; p[2].y=3 ;
    
    for(int i=0; i<3; i++)
    cout << p[i].x << p[i].y << endl;
    L1.get_allocator().deallocate(p,3);
    
    list<MiaStruct2> L2;
    
    L2.push_back(MiaStruct2('a',1));
    L2.push_back(MiaStruct2('b',2));
    L2.push_back(MiaStruct2('c',3));
    
    list<MiaStruct2>::iterator it2;
    for(it2=L2.begin(); it2!=L2.end(); it2++)
    cout << (*it2).x_ << (*it2).y_ << endl;
    
}
Ps: ringrazio il web per aver postato un ottimo esempio di implementazione di una classe generica che faccia uso di liste concatenate per ottenere un vettore dinamico di oggetti.
LoryOne non è collegato   Rispondi citando
Vecchio 07-09-2009, 10.17.02   #8
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
(Y)...
P8257 WebMaster non è collegato   Rispondi citando
Rispondi


Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 ospiti)
 
Strumenti discussione

Regole di scrittura
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is ON
Gli smilies sono ON
[IMG] è ON
Il codice HTML è OFF

Vai al forum

Discussioni simili
Discussione Autore discussione Forum Risposte Ultimo messaggio
vedere lista contatti in gmail con accanto indirizzo x esteso... cippico Software applicativo 1 25-06-2009 08.50.12
Lista dei file caricati sulle periferiche virtuali monroo Software applicativo 1 17-06-2007 11.52.45
Lista nera linee aeree Flying Luka Archivio News Web 29 30-08-2005 16.15.51
CANCELLAZIONE LISTA NUOVO CARTELLA/COLLEGAMENTO w98/me anton Windows 9x/Me/NT4/2000 1 05-05-2004 15.01.13
Excel 2000: problema lista file recenti damiano Office suite 0 31-01-2004 14.23.20

Orario GMT +2. Ora sono le: 15.01.16.


E' vietata la riproduzione, anche solo in parte, di contenuti e grafica.
Copyright © 1999-2017 Edizioni Master S.p.A. p.iva: 02105820787 • Tutti i diritti sono riservati
L'editore NON si assume nessuna responsabilità dei contenuti pubblicati sul forum in quanto redatti direttamente dagli utenti.
Questi ultimi sono responsabili dei contenuti da loro riportati nelle discussioni del forum
Powered by vBulletin - 2010 Copyright © Jelsoft Enterprises Limited.