Aiuto con i puntatori a funzione

di il
24 risposte

Aiuto con i puntatori a funzione

Buonasera a tutti, non riesco a far girare un esercizio con i puntatori a funzione.

class studente{
private:
    char cognome[20];
    char nome[20];
    int matricola;
    float reddito;
public:
    studente();
    void assegna(char*, char*, int, float);
    void stampa();
    friend float maxredd(studente *vet, int);
    friend float minredd(studente *vet, int);
    //friend 
    
};
void input(studente *vet, int);
void print(studente *vet, int);
float operazione(float(*pfun), studente*, int );


int n=0;
    float s=0.0, r1, r2;
    studente* vet=nullptr;
    
    
    cout<<"Inserire il numero di studenti da catalogare: ";
    cin>>n;
    vet=new studente[n];
    if(vet==nullptr){
        cout<<"Impossibile allocare memoria."<<endl;
        return -1;
    }
    
    //float(*pfun)(studente*, int);
    input(vet, n);
    print(vet, n);
    cout<<"Inseire il reddito soglia: ";
    cin>>s;
    maxredd(vet, n);
   
    
  
    r1=operazione(maxredd, vet, n);
    r2=operazione(minredd, vet, n);
    
    //cout<<"Il reddito maggiore e': "<<r1;
    //cout<<"Il reddito minore e': "<<r2;
    
    delete []vet;

studente::studente(){
    strcpy(cognome, " ");
    strcpy(nome, " ");
    matricola=0;
    reddito=0.0;
}

void studente::assegna(char *co, char* no, int mat, float red){
    strcpy(cognome, co);
    strcpy(nome, no);
    matricola=mat;
    reddito=red;
}

void studente::stampa(){
    cout<<"Cognome: "<<cognome<<endl;
    cout<<"Nome: "<<nome<<endl;
    cout<<"Matricola: "<<matricola<<endl;
    cout<<"Reddito: "<<reddito<<endl;
    cout<<"-----------------------"<<endl;
}



void input(studente* vet, int n){
    for(int i=0; i<n; i++){
    char cognome[20], nome [20];
    int matricola;
    float reddito;
    cin.ignore();
    cout<<"Inserire il cognome dello studente: ";
    cin.getline(cognome, 20);
    cout<<"Inserire il nome: ";
    cin.getline(nome, 20);
    cout<<"Inserire la matricola: ";
    cin>>matricola;
    cout<<"Inserire il reddito: ";
    cin>>reddito;
    (vet+i)->assegna(cognome, nome, matricola, reddito);
    cout<<"---------------------------------------"<<endl;
     }
}

void print(studente *vet, int n){
    for(int i=0; i<n; i++){
        (vet+i)->stampa();
    }
}

float maxredd(studente *vet, int n){
    float max=(vet+0)->reddito;
    for(int i=0; i<n; i++){
        if((vet+i)->reddito>max){
            max=(vet+i)->reddito;
        }
    }
    return max;
}

float minredd(studente *vet, int n){
    float min=(vet+0)->reddito;
    for(int i=0; i<n; i++){
        if((vet+i)->reddito<=min){
            min=(vet+i)->reddito;
        }
    }
    return min;
}

float operazione(float(*pfun), studente* vet, int n){
    float z=0.0;
    z=(*pfun)(vet, n);
    return z;
}

Mi potete spiegare dove sbaglio? l'esercizio richiede di calcolare il massimo e minimo reddito.

L'errore che riporta: "main.cpp:46:19: error: 'maxredd' was not declared in this scope";
main.cpp:46:19: error: 'minredd' was not declared in this scope"

24 Risposte

  • Re: Aiuto con i puntatori a funzione

    Le funzioni maxredd e minredd vanno almeno dichiarate prima di usarle nel main, e poi hai dimenticato tutti i parametri del puntatore a funzione in "operazione" :
    
    class studente{
    private:
        char cognome[20];
        char nome[20];
        int matricola;
        float reddito;
    public:
        studente();
        void assegna(char*, char*, int, float);
        void stampa();
        friend float maxredd(studente *vet, int);
        friend float minredd(studente *vet, int);
        //friend 
        
    };
    float maxredd(studente*, int);
    float minredd(studente*, int);
    void input(studente *vet, int);
    void print(studente *vet, int);
    float operazione(float(*pfun)(studente*, int), studente*, int );
    
    
    float operazione(float(*pfun)(studente*, int), studente* vet, int n){
        float z=0.0;
        z=(*pfun)(vet, n);
        return z;
    }
    
    Puoi rinominare il puntatore a funzione con un nome più semplice per non sbagliare:
    
    using FunctionPtr = float (*)(studente*, int);
    float operazione(FunctionPtr, studente* vet, int n);
    
    Visto che sei in C++ e non in C, considera anche di usare l'oggetto function come "contenitore" di funzione, invece di usare i puntatori.
    https://en.cppreference.com/w/cpp/utility/functional/function
    https://cpluspluspedia.com/it/tutorial/2294/std----function--per-avvolgere-qualsiasi-elemento-che-e-callable
  • Re: Aiuto con i puntatori a funzione

    Alexv ha scritto:


    Le funzioni maxredd e minredd vanno almeno dichiarate prima di usarle nel main, e poi hai dimenticato tutti i parametri del puntatore a funzione in "operazione" :
    
    class studente{
    private:
        char cognome[20];
        char nome[20];
        int matricola;
        float reddito;
    public:
        studente();
        void assegna(char*, char*, int, float);
        void stampa();
        friend float maxredd(studente *vet, int);
        friend float minredd(studente *vet, int);
        //friend 
        
    };
    float maxredd(studente*, int);
    float minredd(studente*, int);
    void input(studente *vet, int);
    void print(studente *vet, int);
    float operazione(float(*pfun)(studente*, int), studente*, int );
    
    
    float operazione(float(*pfun)(studente*, int), studente* vet, int n){
        float z=0.0;
        z=(*pfun)(vet, n);
        return z;
    }
    
    Infine la e commerciale quando passi una funzione come parametro:
    
        r1=operazione(&maxredd, vet, n);
        r2=operazione(&minredd, vet, n);
    
    Puoi rinominare il puntatore a funzione con un nome più semplice per non sbagliare:
    
    using FunctionPtr = float (*)(studente*, int);
    float operazione(FunctionPtr, studente* vet, int n);
    
    Visto che sei in C++ e non in C, considera anche di usare l'oggetto function come "contenitore" di funzione, invece di usare i puntatori.
    https://en.cppreference.com/w/cpp/utility/functional/function
    https://cpluspluspedia.com/it/tutorial/2294/std----function--per-avvolgere-qualsiasi-elemento-che-e-callable
    
    class studente{
    private:
        char cognome[20];
        char nome[20];
        int matricola;
        float reddito;
    public:
        studente();
        void assegna(char*, char*, int, float);
        void stampa();
        friend float maxredd(studente *vet, int);
        friend float minredd(studente *vet, int);
        //friend 
        
    };
    float maxredd(studente*, int);
    float minredd(studente*, int);
    void input(studente *vet, int);
    void print(studente *vet, int);
    float operazione(float(*pfun)(studente*, int), studente*, int );
    
    Il problema principale era nell'intestazione . Credevo che bastasse intestarle nella classe visto che le ho dichiarate come friend, non sapevo bisognava reintestarle anche al di fuori... Questa cosa mi ha fatto sbattere la testa un bel po...

    Poi la l'utilizzo corretto della e commerciale misa che non lo capirò mai.. funziona anche se non la metto
  • Re: Aiuto con i puntatori a funzione

    cslash89 ha scritto:


    Poi la l'utilizzo corretto della e commerciale misa che non lo capirò mai.. funziona anche se non la metto
    Sulla è commerciale ho sbagliato io, pardon. Ho modificato il post.

    Quando assegni a un puntatore l'indirizzo di una variabile, la usi vicino alla variabile per ricavarne l'indirizzo.
    Quando copi un puntatore in un altro non serve.
    Il nome della funzione è già di per sé visto come un puntatore, da assegnare a un altro puntatore quando lo passi come parametro a un'altra funzione, quindi non serve.
  • Re: Aiuto con i puntatori a funzione

    L'esercizio l'ho finito, terminado con l'utima parte che chiede di riempire un altro vettore con gli studenti che superano il reddito soglia, ma quando riempio il vettore con più di 1 max 2 elementi, crasha il programma
    
    int n=0, cont=0;
        float s=0.0;
        studente* vet=nullptr;
        studente* newvet=nullptr;
        
        cout<<"Inserire il numero di studenti da catalogare: ";
        cin>>n;
        vet=new studente[n];
        if(vet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        procedura(input, vet, n);
        procedura(print, vet, n);
        cout<<"Il reddito maggiore e': "<<operazione(maxredd, vet, n)<<endl;
        cout<<"Il reddito minore e': "<<operazione(minredd, vet, n)<<endl;
        cout<<"--------------------------"<<endl;
        cout<<"Inseire il reddito soglia: ";
        cin>>s;
        
        newvet=new studente[cont];
        
        if(newvet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        cout<<"Gli studenti con il reddito maggiore alla soglia sono: "<<endl;
        creaElenco(vet, newvet, n, s, cont);
        print1(newvet, cont);
        
        delete []vet;
        delete []newvet;
        cout<<"fine programma."<<endl;
        return 0;
    
    
    class studente{
    private:
        char cognome[20];
        char nome[20];
        int matricola;
        float reddito;
    public:
        studente();
        void assegna(char*, char*, int, float);
        void stampa();
        friend float maxredd(studente *vet, int);
        friend float minredd(studente *vet, int);
        friend float operazione(float(*pfun)(studente *vet, int), studente *vet, int n);
        friend void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont);
    };
    void input(studente *vet, int);
    void print(studente*, int);
    void procedura(void(*p)(studente *vet, int), studente *vet, int n);
    float maxredd(studente *vet, int);
    float minredd(studente *vet, int);
    void creaElenco(studente *vet, studente *newvet, int n, float &s, int &cont);
    void print1(studente *newvet, int cont);
    
    
    
    
    studente::studente(){
        strcpy(cognome, " ");
        strcpy(nome, " ");
        matricola=0;
        reddito=0.0;
    }
    
    void studente::assegna(char *co, char* no, int mat, float red){
        strcpy(cognome, co);
        strcpy(nome, no);
        matricola=mat;
        reddito=red;
    }
    
    void studente::stampa(){
        cout<<"Cognome: "<<cognome<<endl;
        cout<<"Nome: "<<nome<<endl;
        cout<<"Matricola: "<<matricola<<endl;
        cout<<"Reddito: "<<reddito<<endl;
        cout<<"-----------------------"<<endl;
    }
    
    
    
    void input(studente* vet, int n){
        for(int i=0; i<n; i++){
        char cognome[20], nome [20];
        int matricola;
        float reddito;
        cin.ignore();
        cout<<"Inserire il cognome dello studente: ";
        cin.getline(cognome, 20);
        cout<<"Inserire il nome: ";
        cin.getline(nome, 20);
        cout<<"Inserire la matricola: ";
        cin>>matricola;
        cout<<"Inserire il reddito: ";
        cin>>reddito;
        (vet+i)->assegna(cognome, nome, matricola, reddito);
        cout<<"---------------------------------------"<<endl;
         }
    }
    
    void print(studente* vet, int n){
        for(int i=0; i<n; i++){
            (vet+i)->stampa();
        }
    }
    
    float maxredd(studente *vet, int n){
        float max=(vet+0)->reddito;
        for(int i=0; i<n; i++){
            if((vet+i)->reddito>max){
                max=(vet+i)->reddito;
            }
        }
        return max;
    }
    
    float minredd(studente *vet, int n){
        float min=(vet+0)->reddito;
        for(int i=0; i<n; i++){
            if((vet+i)->reddito<=min){
                min=(vet+i)->reddito;
            }
        }
        return min;
    }
    
    float operazione(float(*pfun)(studente *vet, int), studente *vet, int n){
        float z=0.0;
        z=(*pfun)(vet, n);
        
        return z;
    }
    
    void procedura(void(*p)(studente *vet, int), studente *vet, int n){
        (*p)(vet, n);
    }
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        for(int i=0; i<n; i++){
            if((vet+i)->reddito>s){
               *(newvet+cont)=*(vet+i);
                cont++;
             }
        }
    }
    
    void print1(studente* newvet, int c){
        for(int i=0; i<c; i++){
            (newvet+i)->stampa();
        }
    }
    
    
  • Re: Aiuto con i puntatori a funzione

    Hai creato newvet di 0 elementi (cont = 0)...
    Comunque puoi accedere tranquillamente al vettore usando l'indice fra parentesi quadre
  • Re: Aiuto con i puntatori a funzione

    Alexv ha scritto:


    Hai creato newvet di 0 elementi (cont = 0)...
    Comunque puoi accedere tranquillamente al vettore usando l'indice fra parentesi quadre
    Scusami questo ragionamento non l'ho compreso. Se io creo un nuovo vettore, è normale che esso parta da 0 visto che inizialmente è vuoto. Poi con il ciclo for ma mano che trova redditi (se ci sono!) superiori alla soglia, inizia id incrementare e quindi a riempire il vettore..
  • Re: Aiuto con i puntatori a funzione

    Il vettore dinamico che ha il comportamento che dici tu è std::vector
    http://www.cplusplus.com/reference/vector/vector

    Attenzione a studiare bene le basi
  • Re: Aiuto con i puntatori a funzione

    Weierstrass ha scritto:


    Il vettore dinamico che ha il comportamento che dici tu è std::vector
    http://www.cplusplus.com/reference/vector/vector

    Attenzione a studiare bene le basi
    E se volessi creare un vettore normale? Dove sbaglio? Ora non mi interessa creare un vettore dinamico con vector, che per altro ho già usato in altri contesti..
  • Re: Aiuto con i puntatori a funzione

    cslash89 ha scritto:



    Scusami questo ragionamento non l'ho compreso. Se io creo un nuovo vettore, è normale che esso parta da 0 visto che inizialmente è vuoto. Poi con il ciclo for ma mano che trova redditi (se ci sono!) superiori alla soglia, inizia id incrementare e quindi a riempire il vettore..
    Il vettore non cresce automaticamente (a differenza dello std::vector citato dall'utente Weistress).
    Nel main hai
    
    newvet=new studente[cont];
    
    Dove cont è ancora uguale a 0, quindi hai allocato un array di 0 elementi e quando vai a scriverci dentro sei sempre oltre la dimensione massima e quindi ti crasha.
  • Re: Aiuto con i puntatori a funzione

    Alexv ha scritto:


    cslash89 ha scritto:



    Scusami questo ragionamento non l'ho compreso. Se io creo un nuovo vettore, è normale che esso parta da 0 visto che inizialmente è vuoto. Poi con il ciclo for ma mano che trova redditi (se ci sono!) superiori alla soglia, inizia id incrementare e quindi a riempire il vettore..
    Il vettore non cresce automaticamente (a differenza dello std::vector citato dall'utente Weistress).
    Nel main hai
    
    newvet=new studente[cont];
    
    Dove cont è ancora uguale a 0, quindi hai allocato un array di 0 elementi e quando vai a scriverci dentro sei sempre oltre la dimensione massima e quindi ti crasha.
    Ti rigrazio, ora è tutto chiaro. Quindi la procedura esatta dovrebbe essere questa giusto?
    
    creaElenco(vet, newvet, n, s, cont);
    newvet=new studente[cont];
        
        if(newvet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        print1(newvet, cont);
    
  • Re: Aiuto con i puntatori a funzione

    Se gli passi un cont nullo stiamo sempre lì, poi devi caricare il vettore prima di stamparlo.
    Hai 3 strade:
    1) Scansioni il vettore degli studenti due volte, una per trovare il numero di elementi da copiare (e quindi allocare newvet con la dimensione giusta) e un'altra per copiare gli elementi.
    2) Creare newvett direttamente della dimensione del primo.
    3) usare un vettore di appoggio (non so se sia effettivamente più veloce della precedente):
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        int temp*;
        temp = new int[n];
        for(int i=0; i<n; i++){
            if(vet[i] -> reddito > s){
               temp[cont] = i;
                cont++;
             }
          }
         newvet = new studente[cont];
         for(int i=0; i<cont; i++) newvet[i] = vet[temp[i]];
         
         delete[] temp;
    }
    
    Oppure usi std::vector su cui alla fine farai un resize sull'effettivo numero di elementi che hai inserito (per risparmiare memoria).
  • Re: Aiuto con i puntatori a funzione

    Alexv ha scritto:


    Se gli passi un cont nullo stiamo sempre lì, poi devi caricare il vettore prima di stamparlo.
    Hai 3 strade:
    1) Scansioni il vettore degli studenti due volte, una per trovare il numero di elementi da copiare (e quindi allocare newvet con la dimensione giusta) e un'altra per copiare gli elementi.
    2) Creare newvett direttamente della dimensione del primo.
    3) usare un vettore di appoggio (non so se sia effettivamente più veloce della precedente):
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        int temp*;
        temp = new int[n];
        for(int i=0; i<n; i++){
            if(vet[i] -> reddito > s){
               temp[cont] = i;
                cont++;
             }
          }
         newvet = new studente[cont];
         for(int i=0; i<cont; i++) newvet[i] = vet[temp[i]];
         
         delete[] temp;
    }
    
    Oppure usi std::vector su cui alla fine farai un resize sull'effettivo numero di elementi che hai inserito (per risparmiare memoria).
    Mi sfugge una cosa però..
    
    creaElenco(vet, newvet, n, s, cont);
    newvet=new studente[cont];
        
        if(newvet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        print1(newvet, cont);
    
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        for(int i=0; i<n; i++){
            if((vet+i)->reddito>s){
               *(newvet+cont)=*(vet+i);
                cont++;
             }
        }
    }
    
    
    É vero che cont parte da 0, ma una volta creato l'elenco e quindi incrementato cont, la dimensione non dovrebbe aumentare automaticamente? Alla fine sto andado a incrementare il cont del main attraverso la e commerciale..
  • Re: Aiuto con i puntatori a funzione

    cslash89 ha scritto:


    Mi sfugge una cosa però..
    
    creaElenco(vet, newvet, n, s, cont);
    newvet=new studente[cont];
        
        if(newvet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        print1(newvet, cont);
    
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        for(int i=0; i<n; i++){
            if((vet+i)->reddito>s){
               *(newvet+cont)=*(vet+i);
                cont++;
             }
        }
    }
    
    
    É vero che cont parte da 0, ma una volta creato l'elenco e quindi incrementato cont, la dimensione non dovrebbe aumentare automaticamente? Alla fine sto andado a incrementare il cont del main attraverso la e commerciale..
    Nel main che hai postato la new la fai prima di chiamare creaElenco, quando cont è ancora 0.
  • Re: Aiuto con i puntatori a funzione

    Alexv ha scritto:


    cslash89 ha scritto:


    Mi sfugge una cosa però..
    
    creaElenco(vet, newvet, n, s, cont);
    newvet=new studente[cont];
        
        if(newvet==nullptr){
            cout<<"Impossibile allocare memoria."<<endl;
            return -1;
        }
        print1(newvet, cont);
    
    
    void creaElenco(studente* vet, studente* newvet, int n, float &s, int &cont){
        for(int i=0; i<n; i++){
            if((vet+i)->reddito>s){
               *(newvet+cont)=*(vet+i);
                cont++;
             }
        }
    }
    
    
    É vero che cont parte da 0, ma una volta creato l'elenco e quindi incrementato cont, la dimensione non dovrebbe aumentare automaticamente? Alla fine sto andado a incrementare il cont del main attraverso la e commerciale..
    Nel main che hai postato la new la fai prima di chiamare creaElenco, quando cont è ancora 0.
    Si ma nel caso citato, quindi new dopo creaElenco, cont non dovrebbe essere incrementato?
Devi accedere o registrarti per scrivere nel forum
24 risposte