Hoe kan ik een waarde uit een kaart halen?

Ik heb een mapmet de naam valueMapals volgt:

typedef std::map<std::string, std::string>MAP;
MAP valueMap;
...
// Entering data.

Vervolgens geef ik deze kaart door aan een functie:

void function(const MAP &map)
{
  std::string value = map["string"];
  // By doing so I am getting an error.
}

Hoe kan ik de waarde van de kaart krijgen, die wordt doorgegeven als een verwijzing naar een functie?


Antwoord 1, autoriteit 100%

std::map::operator[]is een niet-const-lidfunctie en je hebt een const-referentie.

U moet ofwel de handtekening van functionwijzigen of het volgende doen:

MAP::const_iterator pos = map.find("string");
if (pos == map.end()) {
    //handle the error
} else {
    std::string value = pos->second;
    ...
}

operator[]handelt de fout af door een standaard geconstrueerde waarde aan de kaart toe te voegen en er een verwijzing naar terug te sturen. Dit heeft geen zin als je alleen maar een const-referentie hebt, dus je zult iets anders moeten doen.

U zoude mogelijkheid kunnen negeren en string value = map.find("string")->second;schrijven, als uw programmalogica op de een of andere manier garandeert dat "string"is al een sleutel. Het voor de hand liggende probleem is dat als je het mis hebt, je ongedefinieerd gedrag krijgt.


Antwoord 2, autoriteit 31%

map.at("key")genereert uitzondering als sleutel ontbreekt.

Als k niet overeenkomt met de sleutel van een element in de container, wordt de
functie genereert een out_of_range uitzondering.

http://www.cplusplus.com/reference/map/map/ op/


Antwoord 3, autoriteit 2%

Het antwoordvan Steve Jessoplegt goed uit waarom je std::map::operator[]op een const std::map. Gabe Rainbow’sanswersuggereert een leuk alternatief. Ik zou graag wat voorbeeldcode willen geven over het gebruik van map::at(). Dus, hier is een verbeterd voorbeeld van uw function():

void function(const MAP &map, const std::string &findMe) {
    try {
        const std::string& value = map.at(findMe);
        std::cout << "Value of key \"" << findMe.c_str() << "\": " << value.c_str() << std::endl;
        // TODO: Handle the element found.
    }
    catch (const std::out_of_range&) {
        std::cout << "Key \"" << findMe.c_str() << "\" not found" << std::endl;
        // TODO: Deal with the missing element.
    }
}

En hier is een voorbeeld main()functie:

int main() {
    MAP valueMap;
    valueMap["string"] = "abc";
    function(valueMap, "string");
    function(valueMap, "strong");
    return 0;
}

Uitvoer:

Waarde van sleutel “string”: abc
Sleutel “sterk” niet gevonden

Code op Ideone


Antwoord 4

Het grootste probleem is dat operator[]wordt gebruikt om een ​​waarde in en uit de kaart in te voegen en uit te lezen, dus het kan niet constant zijn.
Als de sleutel niet bestaat, wordt er een nieuw item gemaakt met een standaardwaarde erin, waardoor de kaart groter wordt, die een nieuwe sleutel met een lege tekenreeks zal bevatten, in dit specifieke geval als een waarde als de sleutel dat wel doet bestaat nog niet.
Vermijd operator[]bij het lezen van een kaart en gebruik, zoals eerder vermeld, map.at(key)om gebonden controle te garanderen. Dit is een van de meest voorkomende fouten die mensen vaak maken met kaarten. U moet inserten atgebruiken, tenzij uw code hiervan op de hoogte is. Bekijk deze talk over veelvoorkomende bugs Vreemd terugkerende C++-bugs op Facebook


Antwoord 5

Hoe kan ik de waarde van de kaart krijgen, die wordt doorgegeven als een verwijzing naar een functie?

Nou, je kunt het doorgeven als referentie. De standaard referentiewrapperdus.

typedef std::map<std::string, std::string> MAP;
// create your map reference type
using map_ref_t = std::reference_wrapper<MAP>;
// use it 
void function(map_ref_t map_r)
{
    // get to the map from inside the
    // std::reference_wrapper
    // see the alternatives behind that link
    MAP & the_map = map_r;
    // take the value from the map
    // by reference
    auto & value_r = the_map["key"];
    // change it, "in place"
    value_r = "new!";
}

En de toets.

   void test_ref_to_map() {
    MAP valueMap;
    valueMap["key"] = "value";
    // pass it by reference
    function(valueMap);
    // check that the value has changed
    assert( "new!" == valueMap["key"] );
}

Ik denk dat dit leuk en eenvoudig is. Veel plezier …


Antwoord 6

Hoewel het een beetje laat is, maar ik ga nog steeds antwoorden, dankzij eerdere antwoorden op deze vraag was ik in staat om deze klasse te smeden die pointers en waarden hergebruikt, het creëert twee kaarten om gegevens op te slaan, hier de code als iemand geïnteresseerd is..

template<class T1, class T2> class Bimap
{
std::map<T1, T2*> map1;
std::map<T2, T1*> map2;
public:
    void addRow(T1 &t1, T2 &t2){
        map1.insert(make_pair(t1, &t2));
        map2.insert(make_pair(t2, &t1));
    }
    T2* findForward(T1 t1){
        T2* value = map1.find(t1)->second;
        return value;
    }
    T1* findBackward(T2 t2){
        T1* value = map2.find(t2)->first;
        return value;
    }
};

Klasse gebruiken:

//Init mapp with int,int
Bimap<int,int> mapp;
//Add a row(Record) in bimap
int a = 5;
int b = 7002;
mapp.addRow(a, b);
//Print a record
int *ans= mapp.findForward(a);
cout<<"Bimap Returned:"<<*ans<<endl;

Other episodes