Oppure

Loading
09/02/12 12:28
Daviducci0
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?

#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;
}
aaa
09/02/12 12:49
Nullable
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ì :

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 :

*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 09/02/12 13:35
aaa
09/02/12 14:22
Daviducci0
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?
aaa
09/02/12 18:23
Nullable
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 09/02/12 18:24
aaa
10/02/12 5:57
pierotofy
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:

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).
Il mio blog: piero.dev
10/02/12 6:08
pierotofy
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:

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. :yup:
Ultima modifica effettuata da pierotofy 10/02/12 6:08
Il mio blog: piero.dev
10/02/12 12:55
Daviducci0
Uhm... quindi è consigliabile (quasi obbligatorio) passare gli argomenti per riferimento. Ovvero:
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..
aaa
10/02/12 15:15
pierotofy
Devi passare un puntatore quando stai gestendo dei puntatori (e gli array sono puntatori).
Il mio blog: piero.dev