Daviducci0 (Normal User)
Newbie
Messaggi: 6
Iscritto: 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++ |
#include <iostream> #include <fstream> #include <cstdlib> using namespace std; void carica_vet(char, int, int); void calcola_conta_max(int, int, int ,int) void stampa_vet(int, int) int main() { void carica_vet(); void stampa_vet(); void calcola_conta_max(); system("pause"); return 0; } void carica_vet(char path[], int vet[], int riemp) { riemp = 1; //Inserimento da tastiera del percorso del file da aprire cout <<"Inserire nome del file da aprire:" << endl; cin >> path; // Apro il file fstream f; f.open(path, ios::in); if (!f) // Controllo file { cout << "Errore nell'apertura del file" << endl;; exit(-1); } //Inserisco elementi dal file nel vettore f >> vet[0]; while (!f.eof()) //Continua finché non trovi l'end of file f >> vet[riemp++]; //Inserisci elementi nel vettore riemp--; f.close(); //Chiudo File } void stampa_vet() { cout << "Il vettore inserito e:" << endl; for(int i = 0; i < riemp; i++) { cout << vet[i] << endl; } } void calcola_conta_max(int vet[], int riemp, int max, int contatore) { //Ricerca massimo max=vet[0]; for(int i = 0; i < riemp; i++) { if (vet[i] > max) max = vet[i]; } //Calcolo ripetizione del massimo contatore = 0; for (int i = 0;i < riemp;i++) { if (vet[i] == max) contatore++; } cout <<"Il valore massimo e':" << max << " ed e' ripetuto " << contatore << " volte." << endl; }
|
|
|
Nullable (Normal User)
Expert
Messaggi: 217
Iscritto: 12/07/2011
|
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++ |
int *puntatore;
int valore = 10;
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 |
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 |
|
Daviducci0 (Normal User)
Newbie
Messaggi: 6
Iscritto: 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?
|
|
Nullable (Normal User)
Expert
Messaggi: 217
Iscritto: 12/07/2011
|
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.
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 |
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
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++ |
int *ptr = &var;
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).
|
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
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++ |
void foo(const int &a);
// ...
int b = 0;
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. Ultima modifica effettuata da pierotofy il 10/02/2012 alle 7:08
|
|
Daviducci0 (Normal User)
Newbie
Messaggi: 6
Iscritto: 09/02/2012
|
Uhm... quindi è consigliabile (quasi obbligatorio) passare gli argomenti per riferimento. Ovvero:
Codice sorgente - presumibilmente C++ |
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 &? int main() { char path[256]; int riemp; int vet[100]; carica_vet(path[256], vet[100], riemp); }
|
E invece quando sono costretto ad usare per forza i puntatori???
Comunque grazie entrambi per l'aiuto..
|
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Devi passare un puntatore quando stai gestendo dei puntatori (e gli array sono puntatori).
|
|
Daviducci0 (Normal User)
Newbie
Messaggi: 6
Iscritto: 09/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++ |
#include <iostream> #include <fstream> #include <cstdlib> using namespace std; void carica_vet(char*, int*, int &); void stampa_vet(int*, int &); void ricerca_max(int*, int &, int &, int &); int main() { char *path[256]; //Dichiaro variabili int *vet[100]; int riemp = 1; int max; int contatore = 0; carica_vet(path[256], vet[100], riemp); stampa_vet(vet[100], riemp); ricerca_max(vet[100], riemp, max, contatore); system("pause"); return 0; } void carica_vet(char path[], int vet[], int &riemp) { //Inserimento da tastiera del percorso del file da aprire cout <<"Inserire nome del file da aprire:" << endl; cin >> path; // Apro il file fstream f; f.open(path, ios::in); if (!f) // Controllo file { cout << "Errore nell'apertura del file" << endl;; exit(-1); } //Inserisco elementi dal file nel vettore f >> vet[0]; while (!f.eof()) //Continua finché non trovi l'end of file f >> vet[riemp++]; //Inserisci elementi nel vettore riemp--; f.close(); //Chiudo File } void stampa_vet(int vet[], int &riemp) { cout <<"Il vettore inserito e':" << endl; for(int i = 0; i < riemp; i++) { cout << vet[i] << endl; } } void ricerca_max(int vet[], int &riemp, int &max, int &contatore) {//Ricerca del Massimo max=vet[0]; for(int i = 0; i < riemp; i++) { if (vet[i] > max) max = vet[i]; } //Calcolo ripetizione del massimo for (int i=0;i<riemp;i++) { if (vet[i] == max) contatore++; } // Stampa valore massimo trovato e della sua ripetizione cout <<"Il valore massimo e':" << max << " ed e' ripetuto " <<contatore << "volte." << endl; }
|
Ultima modifica effettuata da Daviducci0 il 10/02/2012 alle 16:43 |
|