2 schichtige Multimap



  • Ich habe einige Fragen zu Multimaps.

    Folgendes:

    typedef std::multimap<std::string, std::multimap<std::string, std::string> > phoneEntry;
    typedef std::pair<std::string, std::multimap <std::string, std::string> >	mainPair;
    typedef std::pair<std::string, std::string>	secPair;
    
    phoneEntry book;
    

    Nun möchte ich in dieses Konglomerat Werte einfügen:

    book.insert (mainPair (name, secPair (ident, value) ));
    

    dabei haben ich dann folgende Fehlermeldung:

    error: no matching function for call to 'std::pair<std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >, std::multimap<std::basic_string<char, std::char_traits<char>, std::
    allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::
    less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::
    allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char>

    , std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >::pair(std::
    basic_string<char, std::char_traits<char>, std::allocator<char> >&, secPair)'

    Stehe da ein wenig im Wald.



  • Suchst du das?

    typedef std::multimap<std::string, std::multimap<std::string, std::string> > PhoneEntryMM;
    typedef std::multimap<std::string, std::string> IdentValueMM;
    
    PhoneEntryMM book;
    
    IdentValueMM *temp = new IdentValueMM;
    temp->insert(IdentValueMM::value_type("Ident","Value"));
    book.insert(PhoneEntryMM::value_type("Name", *temp));
    delete temp;
    

    Achtung dein 2. Argument ist wieder eine Multimap, nicht einfach 2 Strings;
    wolltest du evtl. das machen?:
    typedef std::multimap<std::string, std::pair<std::string, std::string> > PhoneEntryMM;



  • typedef std::pair<std::string, std::multimap <std::string, std::string> >    mainPair;
    

    OK, mainpair besteht also aus einem String und einer weiteren Map.

    Dann

    mainPair (name, secPair (ident, value) )
    

    Verlangt wird ein Paar aus string und map und gegeben wird ein paar aus String und secPair. Ist secPair denn eine Map?
    Mal nachsehen

    typedef std::pair<std::string, std::string>    secPair;
    

    Nö, ist es nicht.

    Also müssen wir secPair anpassen:

    [cpp]typedef std::pair<std::string, std::multimap <std::string, std::string> >    secPair;
    

    [/cpp]

    So. Jetzt passts. Nur brauchen wir aber auch noch eine map, mit der wir das Pair erzeugen können.

    std::map<std::string, std::string> dummyMap;
    
    book.insert (mainPair (name, secPair (ident, dummyMap) ));
    


  • Meine nächste Frage wäre, wie ich auf die interne Multimap zugreifen kann.
    Checker&Murckser 's Lösung funktioniert.

    void phoneBook::insert (std::string* Array) {
    	bookIterand pos = book.find(Array[0]);
    
    	if (pos == book.end()) {
    		subEntry* temp = new subEntry();
    
    		temp->insert(subValue(Array[1], Array[2]));
    
    		this->book.insert(bookValue(Array[0], *temp));
    	} else if (pos.find(Array[1]) == this->book.end()) {//Hier ist ein Fehler
    		//pos ist ein Iterator
    	}
    }
    

    Die Frage ist, wenn pos ein Iterator auf das gefundene Element ist, und ein Iterator Ähnlichkeit mit einem Pointer hat, wie kann man dann über diesen auf den Inhalt zugreifen ?

    Danke für die Hilfe.

    MfG
    Dravian



  • Wo ist das delete passend zum new subEntry. Und wieso erzeugst du das Ding überhaupt dynamisch, wenn du es danach eh nur kopierst und wegwirfst?

    Ich bin zwar gerade ncht sicher, wie jetzt dein book aussieht, vermute aber mal, du meinst soetwas, wie:

    void phoneBook::insert (std::string* Array) { 
        bookIterand pos = book.find(Array[0]); 
    
        if (pos == book.end()) { 
            subEntry temp; 
    
            temp.insert(subValue(Array[1], Array[2])); 
    
            book.insert(bookValue(Array[0], temp)); 
    
        } else if (pos->second.find(Array[1]) == this->book.end()) {
        } 
    }
    


  • Dravian schrieb:

    Meine nächste Frage wäre, wie ich auf die interne Multimap zugreifen kann.
    Checker&Murckser 's Lösung funktioniert.

    void phoneBook::insert (std::string* Array) {
    	bookIterand pos = book.find(Array[0]);
    	
    	if (pos == book.end()) {
    		subEntry* temp = new subEntry();
    		
    		temp->insert(subValue(Array[1], Array[2]));
    		
    		this->book.insert(bookValue(Array[0], *temp));
    	} else if (pos.find(Array[1]) == this->book.end()) {//Hier ist ein Fehler
    		//pos ist ein Iterator
    	}
    }
    

    Die Frage ist, wenn pos ein Iterator auf das gefundene Element ist, und ein Iterator Ähnlichkeit mit einem Pointer hat, wie kann man dann über diesen auf den Inhalt zugreifen ?

    Danke für die Hilfe.

    MfG
    Dravian

    ganz normal über

    if( *pos == /*Inhalt*/ )

    BTW:
    Willst du wissen ob "pos" an der Stelle book.end() steht, oder ob pos auf den gleichen Inhalt, wie book.end() verweist?

    Helium schrieb:

    Wo ist das delete passend zum new subEntry. Und wieso erzeugst du das Ding überhaupt dynamisch, wenn du es danach eh nur kopierst und wegwirfst?

    das mit dem new (und delete übrigens^^) hatte ich oben in meiner Lösung gemacht ...
    weiß gar nicht mehr wieso, aber mit ner Stackvariable gehts natürlich n bissel einfacher -.-



  • Nur zum Verständnis.
    pos ist nacher ein Zeiger auf den Inhalt, aber ist es nun der Zeiger auf das Haupt Multimap oder auf das innere Multimap ?



  • Auch in den Hilfen die ich gefunden habe, finde ich keine Lösung für das problem.



  • Solange wir nciht wissen, wie deine Struktur jetzt letztendlich aussieht können wir auch nicht helfen.



  • Dravian schrieb:

    Nur zum Verständnis.
    pos ist nacher ein Zeiger auf den Inhalt, aber ist es nun der Zeiger auf das Haupt Multimap oder auf das innere Multimap ?

    Wenn es vom Typ bookIterand ist, was wird es dann wohl sein 😉
    Eine Stelle innerhalb der Hauptmultimap würde ich doch schwer vermuten-.-

    /EDIT:
    Ich empfehle an dieser Stelle einfach mal Scott Meyers "Effective STL"



  • nun bis jetzt siehts so aus:

    typedef std::multimap<std::string,
    			std::multimap<std::string, std::string> >	bookType;
    typedef std::multimap<std::string, std::string>			subEntry;
    typedef bookType::iterator								bookIterand;
    typedef subEntry::iterator								subIterand;
    typedef bookType::value_type							bookValue;
    typedef subEntry::value_type							subValue;
    
    class phoneBook {
    	protected:
    		bookType book;
    
    	public:
    		// Konstruktor & Destruktor
    						phoneBook		();
    		virtual			~phoneBook		();
    
    		void 			insert			(std::string* Array);
    
    		std::string		getNumber		(std::string searchValue);
    		std::string		getName			(std::string searchValue);
    		std::string		get				(std::string searchValue, std::string resultType);
    
    		void 			deleteEntry		(std::string* searchValue);
    };
    
    // Implementierung
    
    phoneBook::phoneBook () {
    }
    
    phoneBook::~phoneBook() {
    }
    
    std::string phoneBook::getNumber (std::string searchvalue) {
    	std::ostringstream os;
    
    	bookIterand pos = this->book.find(searchvalue);
    
    	if (pos == this->book.end())
    		os << "Kein Eintrag zu " << searchvalue << " gefunden.\n";
    	else {
    
    		//for (subIterand i = *pos; i <= ; i++) {
    		//}
    		// Hier hab ich halt das gleiche Problem mit den Iteratoren,
    		// da ich hier die interne Multimap durchlaufen will und zum
    		// Beispiel alle Nummern ausgeben.
    	}
    	return os.str();
    }
    
    void phoneBook::insert (std::string name, std::string valueIdent, std::string value) {
    	bookIterand pos = this->book.find(name);
    
    	if (pos == this->book.end()) {
    		subEntry temp ;
    
    		temp.insert(subValue(valueIdent, value));
    		this->book.insert(bookValue(name, temp));
    	} else if (pos.operator ->().find(valueIdent) == this->book.end()) {
    		// oder
    		// pos->second.find(valueIdent) == this->book.second.end()) {
    		// beim oberen sucht er ja an der Position nach dem Key der
    		// durch valueIdent angegeben ist, da der Key doch der von der
    		// Hauptmap ist, kann das nicht funktionieren. Oder denk ich
    		// mal wieder zu kompliziert ?
    	}
    }
    

    das Problem ist halt, das ich die Meldung das es kein second oder first gibt.



  • Dravian schrieb:

    das Problem ist halt, das ich die Meldung das es kein second oder first gibt.

    Echt? also meine Compiler sagen da was anders:

    VC schrieb:

    error C2679: Binärer Operator '==': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operanden vom Typ 'std::_Tree<_Traits>::iterator' akzeptiert (oder keine geeignete Konvertierung möglich)

    gcc schrieb:

    no match for 'operator==' in '(((std::multimap<std::string, std::string, std::lessstd::string, std::allocator<std::pair<const std::string, std::string> > >)(&pos)->std::_Rb_tree_iterator<_Tp>::operator-> [with _Tp = std::pair<const std::string, std::multimap<std::string, std::string, std::lessstd::string, std::allocator<std::pair<const std::string, std::string> > > >]()) + 4u)->std::multimap<_Key, _Tp, _Compare, _Alloc>::find [with _Key = std::string, _Tp = std::string, _Compare = std::lessstd::string, _Alloc = std::allocator<std::pair<const std::string, std::string> >](((const std::string&)((const std::string)(&valueIdent)))) == (((bookType*)((phoneBook*)this)) + 4u)->std::multimap<_Key, _Tp, _Compare, _Alloc>::end [with _Key = std::string, _Tp = std::multimap<std::string, std::string, std::lessstd::string, std::allocator<std::pair<const std::string, std::string> > >, _Compare = std::lessstd::string, _Alloc = std::allocator<std::pair<const std::string, std::multimap<std::string, std::string, std::lessstd::string, std::allocator<std::pair<const std::string, std::string> > > > >]()'

    Also beide sagen, dass kein passender operator == gefunden wurde, was mir im Moment noch nicht so ganz einleuchtet.

    Interessanterweise passiert Beim Comeau-Online-Compiler folgendes:

    In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
    Compiled with C++0x extensions enabled.

    Im Moment habe ich aber auch keine Lust darüber nachzudenken. Du kannst ja trotzdem mal die Meldung deines Compilers posten (der ja angeblich second nicht finden kann, was üverhaupt keinen sinn macht).

    BTW. irgendwie musste ich erstmal eine passende "insert"-Deklaration in deine Klasse einfügen, da "void insert (std::string* Array); " nicht wirlich zu "void phoneBook::insert (std::string name, std::string valueIdent, std::string value)" passt



  • Ok, habs gerade nochmal angeguckt und direkt geschnallt. ISt auch logisch:

    Bei deinem

    pos->second.find(valueIdent) == this->book.end()
    

    Passen die Iteratoren tatsächlich nicht zusammen. Was du willst ist:

    pos->second.find(valueIdent) == pos->second.end()
    

    Dann sollte es gehen.


Anmelden zum Antworten