Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269

    [C++] Dubbio sui puntatori

    Salve ragazzi, ho una perplessità sull'utilizzo dei puntatori:

    Ultimamente ho creato un programmino che permetti di:
    1) Inserire clienti
    2) Ricercare un cliente

    Adesso ho creato una classe Client che aveva i seguenti attributi e metodi:

    cliente.h

    codice:
    class Client
    {
    	private:
    			string Name;
    			string Surname;
    			int	Age;
    
    	public:
    			Client(string Name, string Surname, int Age);
    			void setName(string Name);
    			void setSurname(string Surname);
    			void setAge(int Age);
    			string getName();
    			string getSurname();
    			int getAge();
    };

    Mentre quest'altro è il file .cpp

    codice:
    // Funzione InsertClient: Funzione che mi permette di inserire un cliente
    void InsertClient(Client** tmp, int &i)
    {
    	string name, surname;
    	int age;
    
    	cout << "This is the client number: " << i + 1 << endl;
    	cout << "Insert Name: "		<< endl;
    	cin >> name;
    	cout << "Insert Surname: "	<< endl;
    	cin >> surname;
    	cout << "Insert Age: "		<< endl;
    	cin >> age;
    	*tmp = new Client(name, surname, age);
    }
    
    // Funzione Menu: Funzione che mi permette di gestire le operazioni dell'applicazione
    bool Menu (Client* clients[], int &i)
    {
    	int request;
    
    	cout << "\n\t1. Inserisci cliente: "	<< endl;
    	cout << "\t2. Cerca cliente: "			<< endl;
    	cout << "\t0. Esci: "					<< endl;
    	cin >> request;
    
    	switch(request)
    	{
    		case 1:
    			{
    				InsertClient(&clients[i], i);
    				i++;
    				break;
    			}
    
    		case 2:
    			{
    			
    			string parameter;
    			
    			cout << "\nSurname of client: " << endl;
    			cin >> parameter;
    			bool flag = true;
    			
    			for (int j = 0; j < i; j++)
    			{
    				if (parameter == clients[j]->getSurname())
    				{
    					cout << "\nID client:\t"	<< j + 1;
    					cout << "\nName\t:"			<< clients[j]->getName(); 
    					cout << "\nSurname\t:"		<< clients[j]->getSurname();	
    					cout << "\nAge:\t"			<< clients[j]->getAge() << endl;
    					flag = false;
    					break;
    				}
    			}
    
    			if (flag == true)
    				cout << "The client " << parameter << " don't exist! Try agin please";
    			
    			break;
    			}
    
    		case 0:
    			{
    			cout << "Arrivederci";
    			return false;
    			}
    
    		default:
    			cout << "Scelta sbagliata";
    
    	}
    	
    	return true;
    
    }
    
    // Inizializzo il costruttore
    Client::Client(std::string Name, std::string Surname, int Age)
    {
    	this->Name = Name;
    	this->Surname = Surname;
    	this->Age = Age;
    }
    
    // Le altre funzioni metodi set e get
    void Client::setName(std::string Name)		{ this->Name = Name; }
    void Client::setSurname(std::string Surname)	{ this->Surname = Surname; }
    void Client::setAge(int Age)				{ this->Age = Age; }
    string Client::getName()				{ return Name; }
    string Client::getSurname()				{ return Surname; }
    int Client::getAge()					{ return Age; }
    
    // Enter Point (MAIN)
    int main(int argc, char* argv[])
    {
    	Client* clients[100];
    	int i = 0; // Numero iniziale di clienti
    
    	while (Menu(clients, i)); // loop per il menu
    
    	return 0;
    }

    Premetto che il programma funziona, però adesso vorrei capire una cosa:
    Come mai devo dichiarare per forza un array di puntatori anziche un semplice array di tipo Client?
    Oggi ho provato a passare alla funzione InsertClient, solamente l'elemento da riempire nell'array, ma mi dava errore.
    La mia domanda è: Perchè utilizzare per forza un array di puntatori? e teoricamente come funzionano i doppi puntatori che utilizzo nei parametri formali della funzione InsertClient?

    Grazie anticipatamente!
    Con i sogni possiamo conoscere il futuro...

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    InsertClient riceve una locazione di memoria che contiente un puntatore. Ecco il motivo del doppio puntatore.
    In quanto al "per forza" ho i miei dubbi. Non sta scritto da nessuna parte che è necessario.
    E a dirla tutta io non userei nemmeno un puntatore per Client.
    codice:
    // Funzione InsertClient: Funzione che mi permette di inserire un cliente
    Client* InsertClient(int i) // il riferimento è inutile.
    {
    	string name, surname;
    	int age;
    
    	cout << "This is the client number: " << i + 1 << endl;
    	cout << "Insert Name: "		<< endl;
    	cin >> name;
    	cout << "Insert Surname: "	<< endl;
    	cin >> surname;
    	cout << "Insert Age: "		<< endl;
    	cin >> age;
    	return new Client(name, surname, age);
    }
    ...
    case 1:
    			{
    				clients[i] = InsertClient(i);
    				i++;
    				break;
    			}
    ...
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Scusami, però non riesco a capire.
    Potresti spiegarmi un pò meglio, il problema del puntatore doppio?
    E potresti spiegare anche la tua funzione?

    Grazie mille!
    Con i sogni possiamo conoscere il futuro...

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    codice:
    Client* clients[100];
    Dichiari un array di puntatori a Client che passi alla funzione Menu (che mascherata, riceve un Client* come tipo di dato e un Client** come parametro).

    Alla funzione InsertClient passi una locazione di quell'array per puntatore. Quella locazione però contiene un Client* quindi per riceverlo la InsertClient deve ricevere un Client* come tipo di dato e un Client** come parametro.

    In parole povere Client* non vederlo come puntatore ma come tipo di dato vero e proprio.

    Nella mia funzione, invece di passare una locazione dell'array e metterci un nuovo Client*, lo alloco e lo restituisco subito mettendolo nella locazione i dell'array. Tutto li.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Gentilissimo per la tua ottima risposta, però ho queste ultime perplessità:

    Questa è la funzione Menu:

    codice:
    bool Menu (Client* clients[], int &i)
    qui e come se io scrivessi :

    codice:
    bool Menu (Client** tmp, int &i)
    Penso sia la stessa cosa...

    Il primo puntatore iniziando da sinistra specifica il tipo di variabile puntatoire:

    Client* mentre il 2° puntatore indica l'elemento dell'array.

    Adesso se avessi avuto una funzione "InsertClient" di questo tipo:

    [CODE]void InsertClient (Client* client[], int &i)

    nella funzione Menu, non avrei dovuto utilizzare & per l'indirizzo. Perchè?
    e poi teoricamente nel main io dichiaro l'array di puntatori a clients con una dimensione di 100.
    Perchè quando vado a riempire l'array, ho bisogno di allocare memoria dinamicamente con new?
    Dopo che io ho già dichiarato la dimensione dell'array?

    Grazie ancora, e scusami se continuo ad avere perplessità!
    Con i sogni possiamo conoscere il futuro...

  6. #6
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Ho visto nei thread precedenti che per inserire dinamicamente dati un array, ho bisogno dei puntatori. Però qui, ho dichiarato la dimensione all'array.


    E poi per curiosità principalmente, quando vengono usati i doppi puntatori?
    Con i sogni possiamo conoscere il futuro...

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Scrivere:
    codice:
    bool Menu (Client* clients[], int &i)
    o
    codice:
    bool Menu (Client** clients, int &i)
    per il compilatore è la stessa cosa. La prima forma è scarsamente usata se non nelle prime fasi di sudio del linguaggio, anche se rende meglio l'idea che la funzione deve riceve un array e non un banale puntatore.

    Adesso se avessi avuto una funzione "InsertClient" di questo tipo:
    codice:
    void InsertClient (Client* client[], int &i)
    nella funzione Menu, non avrei dovuto utilizzare & per l'indirizzo. Perchè?
    Se stai parlando di questa riga:
    codice:
    InsertClient(&clients[i], i);
    il compilatore si lamenta.
    Se parli di questa:
    codice:
    while (Menu(clients, i)); // loop per il menu
    Un array decade in un puntatore con lo stesso nome dell'array.
    E' come aver scritto:
    codice:
    while (Menu(&clients[0], i)); // loop per il menu
    e poi teoricamente nel main io dichiaro l'array di puntatori a clients con una dimensione di 100.
    Perchè quando vado a riempire l'array, ho bisogno di allocare memoria dinamicamente con new?
    Dopo che io ho già dichiarato la dimensione dell'array?
    Hai detto al compilatore di riservarti 100 locazioni per i Client*, ma ognuna di queste locazioni non punta a nessun Client. L'allocazione col new serve a quello.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  8. #8
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Quindi da come ho capito devo dichiarare l'array di puntatori, perchè inserisco dinamiacamente i clienti, però quando utilizzo le strutture, la dichiarazione la faccio semplicemente in questo modo:

    codice:
    Client clients[100];
    e poi passo alla funzione in questo modo:

    codice:
    void InserisciCliente (Client *record)
    {
    record->Primoattributo;
    record->Secondoattributo;
    ...
    ...
    ...
    }
    Poi ti domandavo, principalmente i doppi puntatori quando vengono utilizzati?
    Con i sogni possiamo conoscere il futuro...

  9. #9
    se i puntatori in C provocano il mal di testa ai programmatori quelli doppi provocano l'emicrania.
    In C++, quando possibile, è sempre meglio evitarli.

    Comunque l'uso più comune dei puntatori a puntatori è nell'utilizzo dei vettori multidimensionali.
    Per esempio in C scrivo

    char *mesi[] = {"gennaio", "febbraio", "marzo", ... };

    e posso memorizzare stringhe di dimensioni differenti in una sola struttura, senza sprecare memoria, cosa che avrei fatto se avessi utilizzato la struttura dati

    char mesi [][lungh_mese_piu_lungo+1];

    Nel tuo caso non capisco però la necessità di utilizzare puntatori a puntatori, potresti semplicemente crearti una classe contenitore

    codice:
    class Clients {
    
    private:
      
      Client * clients;
    
    public:
      Clients( unsigned int no_clients ) {
        clients = new Client[ no_clients ];
      }
    
       ~Clients () {
          delete [] clients;
      }
      
      Client &getClient ( unsigned int i ) {
        return clients[ i ];
      }
    };
    e passare questa classe per riferimento alle tue funzioni.
    Avrai naturalmente bisogno di un costrutture senza parametri nella classe Client.

    ciao
    sergio

  10. #10
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Premetto che sono alle prime armi con la programmazione orientata agli oggetti.
    Per quanto riguarda la mia classe, mi hanno consigliato di dichiarare gli attributi "private:" in quanto sono dati, sensibili; inoltre ho usato i moduli getter/setter, per quanto i sappia sono molto utilili per settare e stampare a video dati.
    Comunque sergio grazie mille per la tua risposta.

    Ho letto nel tuo intervento che i puntatori doppi vengono utilizzati principalmente per le matrici.
    Però io ho provato a passare una matrice ad una funzione in questo modo, ma non mi permette di passare la matrice.

    codice:
    void InserisciValori (int **miamatrice)
    {
        for (int i = 0; i < 10; i++)
        {
             for (int i = 0; i < 10; i++)
             {
                    miamatrice[i][j] = 0;
             }
        }
    }
    
    int main()
    {
    
    int miamatrice[10][10];
    
    foo (miamatrice);
    
    // Qui stampo i valori della matrice
    
    return 0;
    
    }

    Mentre cosi funziona:

    codice:
    void InserisciValori (int miamatrice[][10])
    {
        for (int i = 0; i < 10; i++)
        {
             for (int i = 0; i < 10; i++)
             {
                    miamatrice[i][j] = 0;
             }
        }
    }
    
    int main()
    {
    
    int miamatrice[10][10];
    
    foo (miamatrice);
    
    // Qui stampo i valori della matrice
    
    return 0;
    
    }
    C'è in questo caso i puntatori doppi a cosa potrebbero servire?

    Grazie!
    Con i sogni possiamo conoscere il futuro...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.