Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 19
  1. #1

    Utilizzare STL::Map

    Ciao a tutti,
    sono alle prese con l'uso del container Map, e se ho capito bene posso utilizzarlo per creare dei semplice hash map..(std::map )

    Non sono fortissimo in programmazione, ma allo stesso tempo penso di capirne qualcosa.
    correggetemi se sbaglio, ma posso definire la mia struttura come una coppia dove il primo elemento è una chiave e il secondo elemento è un dato.

    std::map<std::string, DataMsg> pair;

    dove DataMsg è il tipo di un'oggetto da me definito...
    Ora quello che vorrei chiedervi è: "Posso mettere come chiave (ossia come primo elemento della definizione di map) un'ulteriore oggetto?"

    es: std::map<Current, DataMsg> pair;

    dove Current fondamentalmente è un'oggetto o meglio un'array di tre elementi.. Questa cosa mi crea piccoli errori in fase di compilazione, come posso gestirla?

    Grazie dell'aiuto.
    Giuseppe

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381

    Re: Utilizzare STL::Map

    Originariamente inviato da beppe66
    Non sono fortissimo in programmazione, ma allo stesso tempo penso di capirne qualcosa.
    correggetemi se sbaglio, ma posso definire la mia struttura come una coppia dove il primo elemento è una chiave e il secondo elemento è un dato.
    In genere si, ma dipende dal dato, non dalla mappa.
    Posso mettere come chiave (ossia come primo elemento della definizione di map) un'ulteriore oggetto?"
    Si, a patto che rispetti alcuni vincoli.
    Dev'essere confrontabile con < altrimenti la map non sa come manipolare la chiave.
    In alternativa serve una funzione
    bool comparazione(oggetto a, oggetto b)
    tale che a < b dia true (o false per inserire gli elementi in ordine inverso)
    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

    aiuto con map

    Il mio oggetto che devo usare come chiave è un'array di tre elementi...ciò cosa comporta?
    Non riesco ben a capire quello che mi hai detto..

    Grazie Giuseppe.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Che non puoi usare un array grezzo come chiave della map se non crei una funzione per il confronto. Inoltre non puoi usare direttamente un array, ma solo il puntatore.
    Per capirsi:
    codice:
    		int val1[3] = {0,1,2};
    		int val2[3] = {1,2,3};
    		map<int[3],string> mp;
    
    		mp.insert(make_pair(val1,string("1")));
    		mp.insert(make_pair(val2,string("2")));
    Non compila.
    codice:
    		int val1[3] = {0,1,2};
    		int val2[3] = {1,2,3};
    		map<int*,string> mp;
    
    		mp.insert(make_pair(val1,string("1")));
    		mp.insert(make_pair(val2,string("2")));
    invece si.
    Però così non vengono confrontati gli array, ma solo il valore del puntatore al primo elemento, in questo modo:
    codice:
    key1 < key2
    non
    codice:
    (*key1) < (*key2)
    o
    key1[0] < key2[0]
    Per un simile confronto, devi fare una funzione ( o meglio ancora un functor) apposta.

    Il mio consiglio è di fare qualcosa del genere:
    codice:
    template <typename T, int MassimaDimensioneDelloArray>
    struct MyArrayCompare {
    	bool operator()(T a, T b) {
                    // implementazione del contronto tra array
                    // ad esempio.
    		return (a[0] < b[0]);
    	}
    };
    
    int main() {
    
    		int val1[3] = {0,1,2};
    		int val2[3] = {1,2,3};
    		map<int*,string,MyArrayCompare <int*,3> > mp;
    
    		mp.insert(make_pair(val1,string("1")));
    		mp.insert(make_pair(val2,string("2")));
    
    
    };
    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
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296

    Moderazione

    Il linguaggio di programmazione va indicato anche nel titolo, come da Regolamento.

    Qui l'ho aggiunto io. Tienilo a mente per il futuro.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  6. #6

    C++ usare stl::map

    Ciao di nuovo,
    voglio in primis ringraziarti per le tue risposte complete, sei stato preziosissimo alla mia causa..ihihihih... ti spiego cosa ho fatto perchè c'è ancora qualcosa che non va:

    ho definito come appunto tu mi hai detto una funzione apposta per il confronto:
    template <typename T, int MassimaDimensioneDelloArray>
    struct MyArrayCompare {
    bool operator()(T a, T b) {
    return (a[0] < b[0]);
    }
    };

    dopo di che ho definito come variabile globale(quindi accessibile ad ogni procedura):
    map<int*,DataMsg,MyArrayCompare <int*,3> > mp;

    dove (int *) è la mia chiave formata appunto da quel famoso array di tre elementi e DataMsg è l'oggetto che devo memorizzare associato a quella chiave quindi come secondo elemento non ho più una stringa ma un'oggetto.

    A questo punto ho definito una procedura che mi salva i valori nella struttura e che prende in input il valore di DataMsg che mi deve salvare, quindi "packdata" che vedi come parametro rappresenta proprio DataMsg

    void saveMessage(*packdata){

    int current[3] = {packdata->getCur(0),packdata->getCur(1),packdata->getCur(2)}

    mp.insert(make_pair(current,packdata->getData()));

    for( map<int*,SmallNetDataMsg,MyArrayCompare <int*,3>>::iterator ii=mp.begin(); ii!=mp.end(); ++ii){
    cerr <<"Node datas into Hash : node "<<current[0] << "timestmp :" << (*ii).first[2] << " data :" << (*ii).second.getSd() << endl;
    }
    }

    Effettivamente funziona nel senso che li salva all'interno della struttura, ma il problema ora è che l'ultimo elemento inserito in map viene inserito correttamente, quelli invece precedentemente salvati li vedo visualizzati con valori di chiave casuali.... ossia per esser più chiaro current[0],current[1],current[2] assumono deivalori strani tipo:"123452" ecc.. come se current una volta memorizzato cambiasse valore...Ma che significa?

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Se la mappa è globale, anche gli array devono esserlo, altrimenti spariscono quando vanno fuori scope e i puntatori diventano non più validi.
    Per evitare situazioni del genere devi usare un vector (semplificando anche il functor) :
    codice:
    template <typename T>
    struct MyArrayCompare {
    	bool operator()(const T& a, const T& b) {
                   // massimo indice confrontabile, se serve
                    std::size_t maxComparingSize = std::min(a.size(),b.size());
                    // implementazione del contronto tra array
                    // ad esempio.
    		return (a[0] < b[0]);
    	}
    };
    
    map< vector<int>,string,MyArrayCompare <vector<int> > > mp;
    
    int main() {
    
    		int val1[3] = {0,1,2};
    		int val2[3] = {1,2,3};
    
    		vector<int> v1(&val1[0],&val1[3]);
    		vector<int> v2(&val2[0],&val2[3]);
    
    		mp.insert(make_pair(v1,string("1")));
    		mp.insert(make_pair(v2,string("2")));
    };
    in alternativa, se il tuo compilatore supporta il nuovo std::tr1::array<>, puoi usare quello al posto del vector.
    codice:
    template <typename T>
    struct MyArrayCompare {
    	bool operator()(const T& a, const T& b) {
                   // massimo indice confrontabile, se serve
                    std::size_t maxComparingSize = std::min(a.size(),b.size());
                    // implementazione del contronto tra array
                    // ad esempio.
    		return (a[0] < b[0]);
    	}
    };
    
    map< std::tr1::array<int,3>,string,MyArrayCompare <std::tr1::array<int,3> > > mp;
    
    int main() {
    
    		std::tr1::array<int,3> val1 = {0,1,2};
    		std::tr1::array<int,3> val2 = {1,2,3};
    
    		mp.insert(make_pair(val1,string("1")));
    		mp.insert(make_pair(val2,string("2")));
    };
    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

    C++ usare stl::map

    Ciao di nuovo,
    allora ho messo come dicevi tu la dichiarazione del metodo:

    template <typename T>
    struct MyArrayCompare {
    bool operator()(const T& a, const T& b) {
    // massimo indice confrontabile, se serve
    std::size_t maxComparingSize = std::min(a.size(),b.size());
    // implementazione del contronto tra array
    // ad esempio.
    return (a[0] < b[0]);
    }
    };

    ho dichiarato globale la struttura map e un'array di tre elementi:

    map< vector<int>,DataMsg,MyArrayCompare <vector<int> > > mp;
    int current[3];

    all'interno della procedura SaveMessage ora ho scritto:

    void saveMessage(*packdata){
    //inserisco gli elementi all'interno dell'array
    current[0]=packdata->getCurrent(0);
    current[1]=packdata->getCurrent(1);
    current[2]=packdata->getCurrent(2);

    //creo il vector come appunto mi avevi detto
    vector<int> v1(&current[0],&current[3]);
    //stampo gli elementi
    for( map<vector<int>,DataMsg,MyArrayCompare <vector<int>>>::iterator ii=mp.begin(); ii!=mp.end(); ++ii){
    cerr <<"Node datas into Hash : node "<<(*ii).first[0]<< "timestmp :" << (*ii).first[2] << " data :" << (*ii).second.getSd() << endl;
    }
    }

    Quello che accade è che la stampa fa vedere ogni volta solo un elemento all'interno della struttura...o meglio i problemi rispetto a prima non sono per niente risolti, ho voluto fare una prova allora e ho tolto la parte relativa al confronto all'interno della struttura map e le cose funzionano o meglio inserisce tutti gli elementi che gli dico...la stampa infondo alla procedura saveMessage mi fa vedere tutti gli elementi che intendevo memorizzare

    praticamente ho dichiarato il map in questo modo:
    map< vector<int>,DataMsg> mp;

    Secondo te ho sbagliato in pieno?
    In teoria la parte relativa al confronto di chiave in un'hash map non ci sarebbe più?
    Detto proprio sinceramente non riesco a capire quel terzo campo che prende la definizione di map..
    Grazie Giuseppe

  9. #9
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Per cortesia, inserisci il codice tra i tag indicati al punto 6 del regolamento che trovi qui:
    http://forum.html.it/forum/showthrea...hreadid=973887, altrimenti
    si fa davvero molta fatica a leggere il codice se non si usano.

    Poi ti invito a vedere il codice che ho postato.
    Nel mio codice gli array sono locali alla funzione, per quello ho usato i vector. Se rendi anche gli array globali, il vector non serve più.

    Se intendi continuare a usare i vector (cosa che consiglio caldamente), queste riche puoi modificarle così:
    codice:
    //inserisco gli elementi all'interno dell'array
    Vector v1(3);
    v1[0]=packdata->getCurrent(0);
    v2[1]=packdata->getCurrent(1);
    v2[2]=packdata->getCurrent(2);
    Eliminando un passaggio.

    Per quanto riguarda la mappa, la definizione completa è:
    codice:
    template < class Key, class T, class Compare = less<Key>,
               class Allocator = allocator<pair<const Key,T> > > class map;
    di cui in genere si usano Key e T. Compare invece, volendo in caso di necessità, la possiamo passare noi ed è quello che ho fatto.
    Questo per due motivi:
    1) un puntatore non ha un operatore di confronto.
    2) essendo la chiave un puntatore ad un array, potrei fare alcune operazioni su questo array per stabilire quale sia il minore.
    Ad esempio:
    codice:
    template <typename T>
    struct MyArrayCompare {
    bool operator()(const T& a, const T& b) {
       int x = a[0] + b[1] / a[2]
       int y = b[0]*a[1] -b[2] / a[2];
       return (x < y);
    }
    };
    invece di limitarmi a un confronto tra due elementi e basta come l'altra versione.
    Qui l'algoritmo di confronto lo devi stabilire tu.
    Se basta l'operatore < implementato nel vector, non passare nulla. Se vuoi qualcosa di più complesso, ci devi pensare tu.
    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.

  10. #10

    C++ usare stl::map

    Veramente non so come ringraziarti sei stato veramente forte...
    Voglo scusarmi per non aver taggato il codice, ma sono da poco iscritto a questo forum e diciamo che sono alle prime armi.. Non mancherò comunque in seguito.

    Tornando a noi, penso di aver risolto il problema, sinceramente non ho capito perchè prima il salvataggio non funzionase, ma ho apportato qualche modifica:

    codice:
    template <typename T>
    struct MyArrayCompare {
    	bool operator()(const T& a, const T& b) {
                   // massimo indice confrontabile, se serve
                    std::size_t maxComparingSize = std::min(a.size(),b.size());
                    // implementazione del contronto tra array
                    // ad esempio.
    		return (a[2] < b[2]);
    	}
    };
    ho usato la definizione di map che mi avevi dato
    codice:
    map< vector<int>,DataMsg,MyArrayCompare <vector<int> >>  mp;
    e infine ho modificato la funzione che salvava i dati, eliminando l'array, e facendo solo uso dei vector, in questo modo:

    codice:
    void saveMessage(*packdata){
        
        vector <int>v1(3);
        v1[0]=packdata->getCurrent(0);
        v1[1]=packdata->getCurrent(1);
        v1[2]=packdata->getCurrent(2);
    
        mp.insert(make_pair(v1,packdata->getData()));
    faccio notare che non c'è nè localmente alla funzione nè globalmente la definizione dell'array una definzione dell'array int current[3] che avevo messo nel precedente codice e che a questo punto, come mi hai fatto notare, posso mettere tutto direttamente nel vector.
    Infine vorrei spendere due parole per quel terzo campo della definizione completa di map, ho letto un pò sul web e anche con qualche esempio, ho capito che quello che mi permette di effettuare è un'inserimento ordinato dei miei elementi all'interno della struttura, nel mio caso posso imporre un'ordinamento secondo il terzo elemento che compare nell'array che forma la chiave (a[2] < b[2]).
    Grazie Giuseppe.

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 © 2024 vBulletin Solutions, Inc. All rights reserved.