[C++] aiuto su esercizio puntatori a oggetti

di il
6 risposte

[C++] aiuto su esercizio puntatori a oggetti

Ciao ragazzi volevo chiedervi una mano su un esercizio universitario.
dovrei scrivere le classi necessarie per la gestione dei risultati della fase a gironi dei mondiali di calcio in cui esiste una classe Campionato che al suo interno contiene un elenco di 16 oggetti della classe Squadra ed un elenco di 4 oggetti della classe Girone. Ciascun oggetto della classe Girone al suo interno deve contenere 6 oggetti della classe Partita.
Il primo punto del programma deve avere le seguenti caratteristiche:
1) Funzionalità per l’inserimento del risultato di una partita con la seguente interfaccia:
a. l’operatore introduce il codice del girone (una lettera da ‘A’ a ‘D’)
b. il programma stampa una alla volta le partite ancora da giocare del girone e chiede se si vuole inserire il risultato
c. in caso di risposta affermativa l’utente inserisce il risultato e il programma torna al menu principale altrimenti procede proponendo la partita da giocare successiva

io ho scritto così:
void Campionato::aggiungirisultato(){
     Girone *a,*b,*c,*d;
     char h,n;
     cout<< "Inserisci lettera girone(in maiuscolo)" << endl;
     cin>> h;
     switch(h){
            case 'A':
                for(int i=0;i<6;i++)
                if(p[i]==0){              //errore qui
                a->stampadg(p[i]); //stampa dettagli partita da giocare
                cout<<"Vuoi inserire il risultato? " << endl;
                cin>> n;
                if(n='s'){
                       a->inserisci(p[i]);   
                          }
                else return;
                }
                break;
            case 'B':
                for(int i=0;i<6;i++)
                if(p[i]==0){
                b->stampadg(p[i]); //stampa dettagli partita da giocare
                cout<<"Vuoi inserire il risultato? " << endl;
                cin>> n;
                if(n='s'){
                       b->inserisci(p[i]);   
                          }
                else return;
                }
                break;
            case 'C':
                for(int i=0;i<6;i++)
                if(p[i]==0){
                c->stampadg(p[i]); //stampa dettagli partita da giocare
                cout<<"Vuoi inserire il risultato? " << endl;
                cin>> n;
                if(n='s'){
                       c->inserisci(p[i]);   
                          }
                else return;
                }
                break;
            case 'D':
                for(int i=0;i<6;i++)
                if(p[i]==0){
                d->stampadg(p[i]); //stampa dettagli partita da giocare
                cout<<"Vuoi inserire il risultato? " << endl;
                cin>> n;
                if(n='s'){
                       d->inserisci(p[i]);   
                          }
                else return;
                }
                break;
            default:
                cout << "Scelta non valida." << endl;
        }
return;
}
l'errore che mi da è dovuto al fatto che p(cioè l'array di oggetti di nome Partita) non è incluso in Campionato.h ma in Gestore.h e quindi non so come poterlo definire e risolvere.
ecco come ho scritto le classi:

class Campionato{
      public:
             Campionato(Girone *a,Girone *b,Girone *c,Girone *d);
             void aggiungirisultato();
             void stampastatogirone();
             void stampatutti();
             void modificarisultati();
             void cancellarisultati();
             void setnome(string);
      private:
             string nome;
             Squadra *s[16];
             Girone *g[4];
              };

class Girone{
      public:
             Girone(string,string,string,string);
             void setnome(string);
             void inserisci(Partita *p);
             void modifica(Partita *p);
             void stampag(Partita *p);
             void stampadg();
             void stampatutteg();
             void stampatuttedg();
      private:
              Partita *p[6];
              string nome;
              };
ed ecco il main

int main(){
	Girone a("Italia","Germania","Cina","Korea");
	Girone b("Spagna","Irlanda","Cameroon","Finlandia");
	Girone c("Francia","USA","EAU","Portogallo");
	Girone d("Cipro","Malta","SudAfrica","Brasile");
    Campionato r(a,b,c,d);
    int h;
    while(true){
        cout << "1: Inserisci risultato" << endl;
        cout << "2: Stampa stato girone" << endl;
        cout << "3: Stampa stato tutti i gironi" << endl;
        cout << "4: Modifica risultati" << endl;
        cout << "5: Cancella tutti i risultati" << endl;
        cout << "6: Esci" << endl;
        cin >> h;
        switch(h){
            case 1:
                r.aggiungirisultato();
                break;
            case 2:
                r.stampastatogirone();
                break;
            case 3:
                r.stampatutti();
                break;
            case 4:
                r.modificarisultati();
                break;
            case 5:
                r.cancellarisultati();
                break;
            case 6:
                return 0;
            default:
                cout << "Scelta non valida." << endl;
        }
	}
	return 0;
}
sapreste dirmi come posso risolvere?so che magari la mia richiesta è troppo generica ma ho visto che spesso nel forum aiutate chi è in difficoltà quindi per me che sono alle prime armi potreste darmi una bella mano d'aiuto

6 Risposte

  • Re: [C++] aiuto su esercizio puntatori a oggetti

    Mi sa che devi rivedere il concetto di accesso a variabili interne ad altre classi.
    Quel problema lo risolvi semplicemente fornendo un metodo di accesso a p in Girone:
    
    Partita* Girone::getPartita(int idx) {
       return p[idx];
    }
    ...
    
    case 'A':
        for(int i=0;i<6;i++)
        if(a->getPartita(i)==0){
        //etc.
    
    Il vero problema però è quella
    
        if(a->getPartita(i)==0){
    
    dato che a è un puntatore non valido a girone, il risultato sarà un crash.
  • Re: [C++] aiuto su esercizio puntatori a oggetti

    E allora come dovrei correggerlo?che ne dici se ti faccio vedere tutto il codice che ho scritto.sono 3 piccole classi.
    li trovi qui:
    https://docs.google.com/folder/d/0BzMrCs2n-n-FdUVCR1BnaU9xRHc/edit
    volevo ringraziarti per la risposta di prima e spero che potrai dedicarmi 5 minuti per aiutarmi a risolvere sto problema.da quella che sarà la tua risposta saprò correggere i miei errori.
    grazie sin d'ora
  • Re: [C++] aiuto su esercizio puntatori a oggetti

    Semplicemente togliendo:
    
         Girone *a,*b,*c,*d; // <-- questi.
         char h,n;
         cout<< "Inserisci lettera girone(in maiuscolo)" << endl;
         cin>> h;
    
    che sono variabili locali e non sono quelli che assegni qui:
    
    int main(){
       Girone a("Italia","Germania","Cina","Korea");
       Girone b("Spagna","Irlanda","Cameroon","Finlandia");
       Girone c("Francia","USA","EAU","Portogallo");
       Girone d("Cipro","Malta","SudAfrica","Brasile");
        Campionato r(a,b,c,d); // <-- questi
    
    Ricorda sempre il concetto: variabile locale batte variabile globale. E all'interno di una classe, e solo per la classe, le variabili membro sono a tutti gli effetti variabili globali, per cui se all'interno di una funzione usi variabili locali con lo stesso nome di quelle globali, saranno le variabili locali a essere usate dal compilatore.
    Questo per risolvere il problema dei puntatori.

    Però notò che prima di tutto questo fai errori proprio di sintassi:
    
    void Girone::stampadg(Partita* p) {
        cout << p.nomecasa << " " << p.nometrasferta << endl;
    }
    
    Che significato ha? Stai passando un puntatore non un oggetto, pertanto l'accesso ai dati membri (tra l'altro nemmeno accessibili dato che sono privati di Partita) lo dovresti semmai fare con -> non con ..
    In più la 5° riga del main è proprio sbagliata: stai creando oggetti, non puntatori a oggetti e il costruttore di Campionato accetta solo puntatori. E' un grave errore.

    Tralascio il fatto che passare Partita* p non ha proprio senso dato che l'array di partite è membro di Girone e quindi sempre accessibile da funzioni appartenenti a Girone, ma questo punto al momento è secondario rispetto a quanto detto.
    Riassumendo devi capire che devi usare -> con puntatori a oggetti e . con oggetti fatti e finiti e poi come accedere alle variabili membro di altre classi con opportuni metodi provvisti dalle classi stesse.
    Intanto sistema questo, poi vediamo il resto.
  • Re: [C++] aiuto su esercizio puntatori a oggetti

    Allora ho seguito i tuoi consigli e ho apportato le seguenti modifiche:
    i puntatori locali alla funzione aggiungirisultato che mi avevi segnalati
    
    Girone *a,*b,*c,*d; //<-questi
         char h,n;
         cout<< "Inserisci lettera girone(in maiuscolo)" << endl;
         cin>> h;
    
    li ho rinominati e ho scritto
    
    Girone *ab,*ba,*ca,*da;
         char h,n;
         cout<< "Inserisci lettera girone(in maiuscolo)" << endl;
         cin>> h;
    
    poi per evitare di passare alle funzioni di Girone i puntatori a Partita ho riscritto le classi seguenti:
    questa è la aggiungirisultato
    
    void Campionato::aggiungirisultato(){
         Girone *ab,*ba,*ca,*da;
         char h,n;
         cout<< "Inserisci lettera girone(in maiuscolo)" << endl;
         cin>> h;
         switch(h){
                case 'A':
                    ab->stampadg(); //stampa dettagli partita da giocare
                    break;
                case 'B':
                    ba->stampadg(); //stampa dettagli partita da giocare
                    break;
                case 'C':
                    ca->stampadg(); //stampa dettagli partita da giocare
                    break;
                case 'D':
                    da->stampadg(); //stampa dettagli partita da giocare           
                    break;
                default:
                    cout << "Scelta non valida." << endl;
            }
    return;
    }
    
    questa è la stampadg
    
    void Girone::stampadg(){
         char n;
         for(int i=0;i<6;i++)
         if(p[i]==0){
         cout<< p[i]->nomecasa << " " << p[i]->nometrasferta << endl;
         cout<<"Vuoi inserire il risultato? " << endl;
                    cin>> n;
                    if(n='s'){
                           p[i]->inserisci();   
                              }
                    else return;
                    }
    }
    
    la funzione inserisci di Partita invece è:
    
    void Partita::inserisci(){
         int a,b;
                 cout<< "Inserisci risultato(separati da uno spazio) " << endl;
                 cin>> a >> b;
                 setriscasa(a);
                 setristrasferta(b);
         return;
    }
    
    anche a me sembra pià chiaro e stavolta lo compila ma non si apre nemmeno.
    se potresti gentilmente indicarmi dove erro così ricorreggo e vediamo se funziona.
    in questo caso non ho usato la funzione getPartita che mi avevi consigliato.
    il codice completo lo ritrovi a questo link:
    https://docs.google.com/folder/d/0BzMrCs2n-n-FTmc4dkNEYjZ4Vzg/edit
  • Re: [C++] aiuto su esercizio puntatori a oggetti

    Inoltre volevo chiederti una cosa, se non sembro troppo eccessivo.
    come potrai vedere il costruttore di Girone non l'ho inizializzato perchè non so come fare.
    cioè se il gruppo a è fatto da 4 squadre come faccio a dire che la prima cella dell'arrau deve essere questo gruppo a?
    se scrivo g[0] = a ;
    g[1] = b;
    g[2] = c;
    etc..
    mi da errore perchè non posso fare un assegnamento tra vettori.
    come dovrei fare?
  • Re: [C++] aiuto su esercizio puntatori a oggetti

    pablito92 ha scritto:


    come potrai vedere il costruttore di Girone non l'ho inizializzato perchè non so come fare.
    Non solo quello, non inizializzi nemmeno le variabili in Campionato. Ed è qui che nascono tutti i tuoi problemi. Tra l'altro non ti serve a niente rinominare puntatori locali in Campionato::aggiungirisultato() perché il problema è proprio concettuale: quei puntatori non devono proprio esistere!

    In Campionato hai una array di puntatori a Girone (e uno a Squadra che a mio avviso è sbagliato, dato che una volta formati i gironi, le squadre sono assegnati ai singoli gironi non al campianato, ma per il momento sorvoliamo). Tu al costruttore di campionato passi degli oggetti Girone che non possono essere assegnati a una array di puntatori a Girone, ma devono essere assegnati a un array di Gironi. In altre parole:
    
    Campionato {
       ...
       private:
           Girone g[4];
    };
    
    Campionato::Campionato(Girone a, Girone b, Girone c, Girone d) {
        g[0] = a;
        g[1] = b;
        // etc...
    }
    
    Sono questi gli oggetti che devi usare in Campionato::aggiungirisultato().
    
    Campionato::aggiungirisultato() {
         ...
         switch(h){
                case 'A':
                    g[0].stampadg(); //stampa dettagli partita da giocare
                    break;
                case 'B':
                etc...
    
    Nel costruttore di Girone poi fai riferimento (ancora una volta) a puntatori locali a Squadra. Al di là che è proprio sbagliato per i motivi già citati, quelle variabili sono distrutte appena il costruttore termina, per cui perdi le informazioni.
    Quello che devi fare è mettere un array di Squadra (non puntatori a Squadra) nella classe Girone, in modo che nel costruttore di Girone tu possa fare:
    
    Girone::Girone(string q etc ) {
        g[0].setnome(q);
    }
    
Devi accedere o registrarti per scrivere nel forum
6 risposte