Newsgroup: it.comp.lang.c++
Titolo: Costruttori di copia.

Qualcuno mi spiega come implementare il costruttore di copia per una
struttura dati dinamica realizzata tramite classi?
Grazie


guarda sul sito della prof.Vittorini, ha pubblicato la classe pila con
costruttore di copia. Io sto cercando di eliminare gli errori che c'erano
nei miei programmi di lista e coda dinamica con costruttore di copia...
ciao!

 wrote in message
J%Nza.241549$K35.5...@news2.tin.it...

Eh eh... tutti sotto esame.
Voi che facoltà siete?
Anche sul sito dell'unige potreste trovare qualcosa di didattico, però non
prendetelo troppo sul serio.

 Voi che facoltą siete?
Ing. Informatica a napoli
P.S porc...prima ho postato con il nick per il NG degli U2...;-))
ciao!


allora sono riuscito grazie all'aiuto di un nostro collega a rendere
finalmente funzionante il costruttore di copia della coda dinamica.
classe e Prototipi:
typedef int E;
struct Record{
       E el;
       Record* succ;
      };
typedef Record* Pr;
class Coda{
private:
  Pr testa;
  Pr coda;
public:
Coda();   // costruttore
Coda(const Coda & );
Coda& operator= (const Coda &); //costruttore di copia e overload operatore
assegnazione
~Coda(); // distruttore
void copiacoda(const Coda&);
void Clear();
bool empty() const; // predicato coda vuota
bool full() const;   // predicato coda piena (sempre falso per
implementazione dinamica)
void push(const E el); // inserimento in coda
void pop(E& e);  // prelievo dalla testa
void top(E& e) const;  // ispezione senza rimozione dalla testa
void print()const;
};
Implementazione:
//Costruttore
Coda::Coda(){ testa=0;}
//costruttore di Copia,
Coda::Coda(const Coda & c) {
  copiacoda(c);
}
void Coda::copiacoda(const Coda& c){
     Pr q = c.testa;
     if (q!=0){
        coda = new Record;
        coda->el = q->el;
        testa = coda;
        q = q->succ;
        while(q!=0){
                     coda->succ = new Record;
                     coda = coda->succ;
                     coda->el = q->el;
                     q = q->succ;
                    }
        coda->succ = NULL;
     } else cout<<"Coda Vuota";
}
//ridefinizione operatore di assegnazione
Coda& Coda::operator = (const Coda & c) {
  this->Clear();
  copiacoda(c);
}
//Distruttore
Coda::~Coda(){
  this->Clear();
}
//Clear
void Coda::Clear(){
Pr q;
   for (q=testa; q!=0; testa=q){
       q=testa->succ; //punta al successivo
       delete testa;
   }
}
//Funzione Empty
bool Coda::empty() const { return (testa==0); }
//Funzione Full
bool Coda::full() const { return false; }
//Funzione Push
void Coda::push(const E e){
     Pr p=new Record;
     p->el=e;
     if (testa==0)
        testa=p;
     else
         coda->succ=p;
     p->succ=0;
     coda=p;
}
//funzione Pop
void Coda::pop (E& e){
Pr p=testa;
   if (p!=0){
      e=p->el;
      testa=p->succ;
      delete p;
      }
   else {cout<<"coda vuota per il prelievo"<<endl; exit(1);}
}
void Coda::top(E& e) const {
if (testa!=0) e=testa->el;
else {cout<<"coda vuota per il prelievo"<<endl; exit(1);}
}
void Coda::print() const
{
Pr q = testa;
while (q!=0){
cout << "Elemento: " << q->el << " ";
q = q->succ;
}
}
Nel main:
void inserimento(Coda& c);
void presenta_menu(int& scelta);
void eliminazione(Coda& c);
int main()
{
  Coda c;
     inserimento(c);
     inserimento(c);
     inserimento(c);
     c.print();
     system("PAUSE");
     Coda c1=c;
     c1.print();
     system("PAUSE");
    return 0;
}
void inserimento(Coda& c){
  E e;
  cout<<"1)Inserimento di un elemento"<<endl;
  cout<<"Elemento:";
  cin>>e;
  c.push(e);
}
void eliminazione(Coda& c){
  E e;
  if (!c.empty()){
    cout<<"2)Eliminazione di un elemento"<<endl;
    c.pop(e);
    cout<<"Elemento Eliminato:"<<e;
    getchar();
  }
  else cout<<"Coda vuota! Operazione impossibile";
  getchar();
}
più tardi posto la lista dinamica...


per quanto riguarda la lista ho qualche problema: il programma esegue si' la
copia, ma solo del primo elemento della lista!
ci date una mano?
ecco il codice:
prototipi e classe:
typedef int E;
struct Record{
       E elem;
       Record* punt;
       };
typedef Record* L;
class lista{
      private:
      L l;
      void inserisciric(L& l, E e);
      void eliminaric(L& l, E e);
      void elimina_testa(L& l);
      public:
      lista(){ l=0;}
      lista(const lista &);
      lista& operator=(const lista & );
      ~lista();
      void copialista(const lista &);
      void push(E e);
      void pop(E e);
      void inserisci(E e){ inserisciric(l,e);}
      void elimina(E e){ inserisciric(l,e);}
      bool empty(){ return (l==0);}
      void top(E e);
      void print()const;
      };
implementazione:
//costruttore di copia
lista::lista(const lista& lista) {
  copialista(lista);
}
//ridefinizione operatore di assegnazione
lista& lista::operator = (const lista& lista) {
    copialista(lista);
}
lista::~lista(){
           L q,p;
           for (p=l; p!=0; p=q){
               q=p->punt;
               delete p;
              }
}
//funzione copia elemento per elemento, richiamata nel costruttore di copia
void lista::copialista(const lista & lista){
L q = lista.l;   //Creiamo un puntatore d'appoggio
       if (q!=0){        //Testiamo se la lista da copiare è vuota
             l = new Record;   //Allochiamo una nuova struct
             l->elem=q->elem;   //Copiamo i campi
             //l->punt=l;
             q=q->punt;  //Avanziamo col punt. nella lista da copiare
             while(q!=0){  //Cicliamo fino a che non termina la lista
                 l->punt = new Record; //Accodiamo nuove struct
                 l = l->punt;
                 l->elem = q->elem;
                 q=q->punt;
             }
             l->punt=0; //Poniamo il campo punt dell'ultima struct a zero
       }
       else cout<<"Lista Vuota";
}
void lista::inserisciric(L& l, E e){
     if ((l==0) || (e<l->elem))
     push(e);
     else inserisciric (l->punt, e);
}
void lista::eliminaric(L& l, E e){
     if (l!=0){
        if(e==l->elem) elimina_testa(l);
        else eliminaric(l->punt,e);
     }
}
void lista::elimina_testa(L& l){
     L ltemp=l->punt;
     delete l;
     l=ltemp;
}
void lista::push(E e){
     L q=new Record;
     q->elem=e;
     q->punt=l;
     l=q;
}
void lista::pop(E e){
     if (l!=0){
        e=l->elem;
        L q=l;
        l=l->punt;
        delete q;
        }
     else cout<<"Operazione impossibile, lista vuota!";
}
void lista::top(E e){
     if(l!=0) e=l->elem;
       else cout<<"Lista vuota per richiesta top!";
}
void lista::print() const
{
L q = l;
while (q!=0){
cout << "Elemento: " << q->elem << " ";
q = q->punt;
}
}
ciao!

}
Manca un "return *this"; strano che siate riusciti
a compilare questo codice... di solito i compilatori
C++ sono schizzinosi su errori di questo tipo.
HTH
Andrea

 Mi permetto qualche commento...
grazie dei consigli ;-)) puoi dare un'occhiata anche al codice della lista??
ciao e grazie!!!

 }
Ma come fanno a funzionarti sti programmi?!?
Questa funzione dovrebbe ritornare un valore!!!

"Lancer" <pepp...@TOGLIEREtiscali.it> ha scritto nel messaggio
news:baq6bc$eth$1...@lacerta.tiscalinet.it...

per funzionare funziona! se aggiungi il return *this non cambia nulla...
ciao!

 nulla...
Come non cambia nulla...cambia che cosi' compila...

 ciao!
HTH
Andrea
PS: Nota che questa roba l'ho scritta e nemmeno
    compilata. Ti sconsiglio vivamente di prenderla
    come oro colato; piuttosto ragionaci su e se
    ti quadra bene, se non ti quadra andiamo a
    fondo della cosa.

> }
Io di questo funzione elimina ricorsiva non sono convinto...
Se l'elemento dal eliminare e' nel mezzo della lista, il puntatore
all'elemento precedente si perde. Di conseguenza mi ritorna una lista
spezzata nel punto di eliminazione...
O no?

O no?
elimina_testa riceve l come reference; quindi quando
viene eseguito l=ltemp stai modificando il "punt" del
nodo precedente oppure il membro "l" della lista
(perche' anche eliminaric riceve l per reference e
viene chiamata passando il membro l).
Nel post mi sono anche scordato di un ulteriore
consiglio: cercate di usare nomi sensati in modo
uniforme (quindi o sono maiuscoli o sono minuscoli,
o c'e' l'underscore che separa le parole oppure non
c'e') e cercate di evitare sovrapposizioni gratuite,
come chiamare "l" un parametro quando e' anche un
membro della classe (oppure chiamare una variabile
lista quando lista e' il nome della classe).
HTH
Andrea

     fondo della cosa.
funziona!!! questo č la funzione copialista:
void lista::copialista(const lista & lista){
     L q = lista.l; //Creiamo un puntatore d'appoggio
     if (q!=0) {        //Testiamo se la lista da copiare č vuota
             l = new Record;   //Allochiamo una nuova struct
             l->elem = q->elem;   //Copiamo i campi
             q = q->punt;  //Avanziamo col punt. nella lista da copiare
             L t = l;
             while(q!=0){  //Cicliamo fino a che non termina la lista
                 t->punt = new Record; //Accodiamo nuove struct
                 t = t->punt;
                 t->elem = q->elem;
                 q = q->punt;
             }
             t->punt = 0; //Poniamo il campo punt dell'ultima struct a zero
       }
        l=0;
        else cout<<"Lista Vuota";
}
ho pensato di mettere in una funzione l'algoritmo contenuto nel distruttore
e richiamarlo cosě all'inizio del costruttore di copia:
this->clean();
dove clean č appunto la funzione che si occupa di deallocare la
struttura....
ciao!

  }
grande! questa mi serviva proprio!!! ;-))