Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Delucidazioni tra funzioni e il passaggio per valore e riferimento
Forum - C/C++ - Delucidazioni tra funzioni e il passaggio per valore e riferimento

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Daviducci0 (Normal User)
Newbie


Messaggi: 6
Iscritto: 09/02/2012

Segnala al moderatore
Postato alle 13:28
Giovedì, 09/02/2012
Salve a tutti ragazzi... sono un neo studente di ingegneria informatica con conoscenza 0 del linguaggio e l'unica cosa che ancora non riesco a capire è come funzione il passaggio delle variabili tra il main e la funzione, ovvero quando bisogna mettere l'* o la &.

Ho questo compito: Carica un vettore da file e calcolare il massimo e contare quante volte è ripetuto il massimo.

Inserendo tutte le istruzioni nel main, il programma riesco a farlo, funziona e fa tutto quello che deve fare ma se voglio creare delle funzioni vado in panico e non riesco più a farlo. Ora vi riporto il codice con la divisione dei sottoprogrammi e i relativi algoritmi, potete spiegarmi dove e come inserire le varie variabili?

Codice sorgente - presumibilmente C++

  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstdlib>
  4.  
  5. using namespace std;
  6.  
  7. void carica_vet(char, int, int);
  8. void calcola_conta_max(int, int, int ,int)
  9. void stampa_vet(int, int)
  10.  
  11.  
  12. int main()
  13. {  
  14.     void carica_vet();
  15.     void stampa_vet();
  16.     void calcola_conta_max();
  17.    
  18.    
  19.     system("pause");
  20.     return 0;
  21.        
  22. }
  23.  
  24. void carica_vet(char path[], int vet[], int riemp)
  25. {    
  26.     riemp = 1;
  27.    
  28.     //Inserimento da tastiera del percorso del file da aprire  
  29.     cout <<"Inserire nome del file da aprire:" << endl;
  30.     cin >> path;
  31.    
  32.     // Apro il file
  33.     fstream f;
  34.     f.open(path, ios::in);
  35.     if (!f)                                                     // Controllo file
  36.     {
  37.         cout << "Errore nell'apertura del file" << endl;;
  38.         exit(-1);
  39.     }
  40.    
  41.     //Inserisco elementi dal file nel vettore
  42.     f >> vet[0];
  43.    
  44.     while (!f.eof())              //Continua finché non trovi l'end of file
  45.         f >> vet[riemp++];        //Inserisci elementi nel vettore
  46.     riemp--;
  47.  
  48.     f.close();             //Chiudo File
  49. }
  50.  
  51.  
  52. void stampa_vet()
  53. {
  54.      cout << "Il vettore inserito e:" << endl;
  55.      for(int i = 0; i < riemp; i++)
  56.     {
  57.        cout << vet[i] << endl;
  58.     }
  59. }
  60.  
  61.  
  62. void calcola_conta_max(int vet[], int riemp, int max, int contatore)
  63. {
  64.    //Ricerca massimo
  65.    max=vet[0];  
  66.    for(int i = 0; i < riemp; i++)
  67.     {
  68.        if (vet[i] > max)
  69.            max = vet[i];
  70.     }
  71.    
  72.    //Calcolo ripetizione del massimo
  73.    contatore = 0;
  74.    
  75.    for (int i = 0;i < riemp;i++)
  76.    {
  77.       if (vet[i] == max)
  78.       contatore++;
  79.    }
  80.    cout <<"Il valore massimo e':" << max << " ed e' ripetuto " << contatore << " volte." << endl;
  81. }


PM Quote
Avatar
Nullable (Normal User)
Expert


Messaggi: 217
Iscritto: 12/07/2011

Segnala al moderatore
Postato alle 13:49
Giovedì, 09/02/2012
L'operatore * ( chiamato anche operatore diretto o non referenziato ) serve ad assegnare all'oggetto un valore a cui un puntatore fa riferimento. Invece l'operatore & ( chiamato anche operatore unario o monadico ) restituisce l'indirizzo in memoria di una variabile. Entrambi gli operatori, se volessero essere utilizzati per scrivere 2 righe di codice, potrebbero essere utilizzati così :

Codice sorgente - presumibilmente C/C++

  1. int *puntatore;
  2. int valore = 10;
  3. puntatore = &valore;



Nella prima riga si dichiara un puntatore di tipo numerico e lo si chiama puntatore, la seconda riga dichiara una variabile numerica il cui valore è 10 e infine nella terza riga viene assegnato il contenuto della variabile valore alla variabile puntatore, questo significa che - in un certo senso - il contenuto ( 10 in questo caso ) della variabile valore viene "copiato" nella variabile di tipo puntatore. Parlando di funzioni, e in particolar modo quando si parla di passaggio di puntatori a funzione non si fa altro che passare ad una funzione il rispettivo indirizzo in memoria e questo passaggio viene chiamato passaggio di parametri per riferimento.

Tornando un attimo all'esempio di prima : è possibile ulteriormente modificare il contenuto della variabile puntatore scrivendo :

Codice sorgente - presumibilmente Plain Text

  1. *puntatore = 20;



questo perché l'operatore * serve per prendere l'indirizzo in memoria della variabile puntatore ( e quindi anche il suo contenuto ) e l'operatore di assegnazione = fornisce un nuovo valore al contenuto della variabile.

P.S: Se modifico il contenuto di un puntatore NON MODIFICO IL CONTENUTO DELLA VARIABILE CHE HA "RIEMPITO" IL PUNTATORE.

P.P.S: Quando si richiama una funzione non c'è bisogno di scrivere il tipo di ritorno, come hai fatto tu nel main.

Spero tu abbia capito.

Ultima modifica effettuata da Nullable il 09/02/2012 alle 14:35
PM Quote
Avatar
Daviducci0 (Normal User)
Newbie


Messaggi: 6
Iscritto: 09/02/2012

Segnala al moderatore
Postato alle 15:22
Giovedì, 09/02/2012
Allora per il problema del tipo di ritorno è stata una mia svista, chiedo scusa.

Il concetto in sè di puntatore mi era chiaro: cioè variabile che non contiene direttamente  un valore ma un indirizzo di memoria in cui è contenuto il valore, correggimi se sbaglio.

Il problema nasce quando devo creare queste funzioni e regolare i vari passaggi. Ho visto in giro di funzioni dove ne loro argomento c'erano variabili con il prefisso & o *. Nel primo caso si crea una copia della variabile mentre nella seconda si punta direttamente alla variabile considerata giusto?

PM Quote
Avatar
Nullable (Normal User)
Expert


Messaggi: 217
Iscritto: 12/07/2011

Segnala al moderatore
Postato alle 19:23
Giovedì, 09/02/2012
Testo quotato

Postato originariamente da Daviducci0:
Il concetto in sè di puntatore mi era chiaro: cioè variabile che non contiene direttamente  un valore ma un indirizzo di memoria in cui è contenuto il valore, correggimi se sbaglio.



Esatto.

Testo quotato

Postato originariamente da Daviducci0:Ho visto in giro di funzioni dove ne loro argomento c'erano variabili con il prefisso & o *. Nel primo caso si crea una copia della variabile mentre nella seconda si punta direttamente alla variabile considerata giusto?



Anche questo è esatto.

Ultima modifica effettuata da Nullable il 09/02/2012 alle 19:24
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 6:57
Venerdì, 10/02/2012
Testo quotato

Postato originariamente da Nullable:
questo perché l'operatore * serve per prendere l'indirizzo in memoria della variabile puntatore ( e quindi anche il suo contenuto )



C'e' un po' di imprecisione qui... l'operatore * e' chiamato "dereference operator" (operatore di dereferenziazione) e non prende nessun indirizzo, l'indirizzo esiste gia'.

Se hai un puntatore:

Codice sorgente - presumibilmente C/C++

  1. int *ptr = &var;
  2. std::cout << *ptr



Nella prima riga l'asterisco e' usato come regola per definire un tipo puntatore ad int, nella seconda e' usato per accedere al contenuto dell'indirizzo di ptr. E' un concetto semplice.

Ogni puntatore e' un intero che ha un valore equivalente ad un indirizzo di memoria. Quando utilizzi * prima del nome della variabile, accedi al contenuto di quell'indirizzo (dereferenzi il puntatore).


Il mio blog: https://piero.dev
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 7:08
Venerdì, 10/02/2012
Testo quotato

Postato originariamente da Daviducci0:
Ho visto in giro di funzioni dove ne loro argomento c'erano variabili con il prefisso & o *. Nel primo caso si crea una copia della variabile mentre nella seconda si punta direttamente alla variabile considerata giusto?



No.

Quando utilizzi * stai passando alla funzione un puntatore. Quando utilizzi & stai passando un riferimento (che e' una sorta di puntatore, ma diverso). Le performance sono praticamente uguali ed in ogni caso NON viene fatta una copia della variabile.

Il beneficio di passare per riferimento (&) e' che un riferimento non puo' essere riassegnato o fatto puntare ad un altro oggetto, mentre un puntatore puo' essere fatto puntare ad un oggetto diverso. Oltre a questo puoi usare la notazione (oggetto.metodo() invece che oggetto->metodo() oppure (*oggetto).metodo()), che da alcuni e' considerato piu' pulito.

Una bella abitudine se si vuole passare un argomento ad una funzione per riferimento e ci si vuole assicurare che non sia modificato e' di dichiarare le funzioni in questa maniera:

Codice sorgente - presumibilmente C/C++

  1. void foo(const int &a);
  2.  
  3. // ...
  4. int b = 0;
  5. foo(b);



Il const si occupera' di assicurare che "b" non venga modificato durante la chiamata a foo. Usa i parametri per riferimento il piu' possibile, e i puntatori il meno possibile. :yup:

Ultima modifica effettuata da pierotofy il 10/02/2012 alle 7:08


Il mio blog: https://piero.dev
PM Quote
Avatar
Daviducci0 (Normal User)
Newbie


Messaggi: 6
Iscritto: 09/02/2012

Segnala al moderatore
Postato alle 13:55
Venerdì, 10/02/2012
Uhm... quindi è consigliabile (quasi obbligatorio) passare gli argomenti per riferimento. Ovvero:
Codice sorgente - presumibilmente C++

  1. void carica_vet(char &path[ ], int &vet[ ], int &riemp) // Devo aggiungere const prima di ogni diachiarazione? p.s. essendo vet[ ] e path[ ] dei vettori, c'è bisogno del &?
  2.  
  3. int main()
  4. {
  5.     char path[256];
  6.     int riemp;
  7.     int vet[100];
  8.    
  9.     carica_vet(path[256], vet[100], riemp);
  10. }



E invece quando sono costretto ad usare per forza i puntatori???

Comunque grazie entrambi per l'aiuto..

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 16:15
Venerdì, 10/02/2012
Devi passare un puntatore quando stai gestendo dei puntatori (e gli array sono puntatori).


Il mio blog: https://piero.dev
PM Quote
Avatar
Daviducci0 (Normal User)
Newbie


Messaggi: 6
Iscritto: 09/02/2012

Segnala al moderatore
Postato alle 16:41
Venerdì, 10/02/2012
Sono riuscito in parte a modificare tutto il codice iniziale con i sottoprogrammi ma continua ad esserci un errore in fase di run causandomi un force closed:
(Mi sa che sbaglio nel creare "int *vet e il char *path nel main")
Codice sorgente - presumibilmente C++

  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstdlib>
  4.  
  5. using namespace std;
  6.  
  7. void carica_vet(char*, int*, int &);
  8. void stampa_vet(int*, int &);
  9. void ricerca_max(int*, int &, int &, int &);
  10.  
  11.  
  12. int main()
  13. {
  14.     char *path[256];  //Dichiaro variabili
  15.     int *vet[100];
  16.     int riemp = 1;
  17.     int max;
  18.     int contatore = 0;
  19.  
  20.     carica_vet(path[256], vet[100], riemp);
  21.     stampa_vet(vet[100], riemp);
  22.     ricerca_max(vet[100], riemp, max, contatore);
  23.  
  24.     system("pause");
  25.     return 0;
  26.  
  27. }
  28.  
  29.  
  30. void carica_vet(char path[], int vet[], int &riemp)
  31. {
  32.     //Inserimento da tastiera del percorso del file da aprire
  33.     cout <<"Inserire nome del file da aprire:" << endl;
  34.     cin >> path;
  35.  
  36.     // Apro il file
  37.  
  38.     fstream f;
  39.     f.open(path, ios::in);
  40.     if (!f)                                                     // Controllo file
  41.     {
  42.         cout << "Errore nell'apertura del file" << endl;;
  43.         exit(-1);
  44.     }
  45.  
  46.  
  47.     //Inserisco elementi dal file nel vettore
  48.     f >> vet[0];
  49.  
  50.     while (!f.eof())              //Continua finché non trovi l'end of file
  51.         f >> vet[riemp++];        //Inserisci elementi nel vettore
  52.     riemp--;
  53.  
  54.  
  55.     f.close();             //Chiudo File
  56. }
  57.  
  58. void stampa_vet(int vet[], int &riemp)
  59. {
  60.     cout <<"Il vettore inserito e':" << endl;
  61.  
  62.     for(int i = 0; i < riemp; i++)
  63.     {
  64.         cout << vet[i] << endl;
  65.     }
  66.  
  67. }
  68.  
  69.  
  70. void ricerca_max(int vet[], int &riemp, int &max, int &contatore)
  71. {//Ricerca del Massimo
  72.  
  73.     max=vet[0];
  74.  
  75.     for(int i = 0; i < riemp; i++)
  76.     {
  77.         if (vet[i] > max)
  78.             max = vet[i];
  79.     }
  80.  
  81.  
  82.     //Calcolo ripetizione del massimo
  83.  
  84.     for (int i=0;i<riemp;i++)
  85.     {
  86.         if (vet[i] == max)
  87.         contatore++;
  88.     }
  89.  
  90.     // Stampa valore massimo trovato e della sua ripetizione
  91.     cout <<"Il valore massimo e':" << max << " ed e' ripetuto " <<contatore << "volte." << endl;
  92. }


Ultima modifica effettuata da Daviducci0 il 10/02/2012 alle 16:43
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo