J'essaie de vérifier si une clé est dans une carte et ne peut pas le faire:
typedef map<string,string>::iterator mi;
map<string, string> m;
m.insert(make_pair("f","++--"));
pair<mi,mi> p = m.equal_range("f");//I'm not sure if equal_range does what I want
cout << p.first;//I'm getting error here
alors, comment puis-je imprimer ce qui est dans p?
Utilisez map::find
_if ( m.find("f") == m.end() ) {
// not found
} else {
// found
}
_
Pour vérifier si une clé particulière de la carte existe, utilisez la fonction membre count
de l'une des manières suivantes:
m.count(key) > 0
m.count(key) == 1
m.count(key) != 0
La documentation pour map::find
indique: "Une autre fonction membre, map::count
, peut être utilisée pour vérifier si une clé particulière existe."
La documentation pour map::count
indique: "Comme tous les éléments d'un conteneur de carte sont uniques, la fonction ne peut renvoyer que 1 (si l'élément est trouvé) ou zéro (sinon)."
Pour récupérer une valeur de la carte via une clé dont vous savez qu’elle existe, utilisez map :: at :
value = m.at(key)
Contrairement à map :: operator [] , map::at
ne créera pas de nouvelle clé dans la carte si la clé spécifiée n'existe pas.
Vous pouvez utiliser .find()
:
map<string,string>::iterator i = m.find("f");
if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }
m.find == m.end() // not found
Si vous voulez utiliser une autre API, trouvez alors allez pour m.count(c)>0
if (m.count("f")>0)
cout << " is an element of m.\n";
else
cout << " is not an element of m.\n";
C++ 2 nous donne std::map::contains
pour le faire.
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> example = {{1, "One"}, {2, "Two"},
{3, "Three"}, {42, "Don\'t Panic!!!"}};
if(example.contains(42)) {
std::cout << "Found\n";
} else {
std::cout << "Not found\n";
}
}
Je pense que vous voulez map::find
. Si m.find("f")
est égal à m.end()
, la clé est introuvable. Sinon, find renvoie un itérateur pointant sur l'élément trouvé.
L'erreur est due au fait que p.first
est un itérateur qui ne fonctionne pas pour l'insertion de flux. Changez votre dernière ligne en cout << (p.first)->first;
. p
est une paire d'itérateurs, p.first
est un itérateur, p.first->first
est la chaîne de clé.
Une carte ne peut avoir qu'un seul élément pour une clé donnée, donc equal_range
n'est pas très utile. C'est défini pour map, car il est défini pour tous les conteneurs associatifs, mais c'est beaucoup plus intéressant pour multimap.
map<string, string> m;
clé de contrôle existe ou non, et retourne le nombre d'occurrences (0/1 dans la carte):
int num = m.count("f");
if (num>0) {
//found
} else {
// not found
}
clé de contrôle existe ou pas, et retourne itérateur:
map<string,string>::iterator mi = m.find("f");
if(mi != m.end()) {
//found
//do something to mi.
} else {
// not found
}
dans votre question, l'erreur provoquée par une surcharge operator<<
mauvaise, parce que p.first
est map<string, string>
, vous ne pouvez pas l'imprimer. essaye ça:
if(p.first != p.second) {
cout << p.first->first << " " << p.first->second << endl;
}
template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
return (container.find(key) != std::end(container));
}
Bien sûr, si vous voulez devenir plus chic, vous pouvez toujours créer une fonction qui prend aussi une fonction trouvée et une fonction non trouvée, quelque chose comme ceci:
template <typename T, typename Key, typename FoundFunction, typename NotFoundFunction>
void find_and_execute(const T& container, const Key& key, FoundFunction found_function, NotFoundFunction not_found_function)
{
auto& it = container.find(key);
if (it != std::end(container))
{
found_function(key, it->second);
}
else
{
not_found_function(key);
}
}
Et utilisez-le comme ceci:
std::map<int, int> some_map;
find_and_execute(some_map, 1,
[](int key, int value){ std::cout << "key " << key << " found, value: " << value << std::endl; },
[](int key){ std::cout << "key " << key << " not found" << std::endl; });
L'inconvénient de cette idée est de trouver un bon nom, "find_and_execute" est maladroit et je ne peux rien trouver de mieux à mon esprit ...
Faites attention en comparant le résultat de la recherche avec la fin, comme pour la carte 'm', comme toutes les réponses l'ont fait ci-dessus, map :: iterator i = m.find ("f");
if (i == m.end())
{
}
else
{
}
vous ne devez pas essayer d’effectuer une opération telle que l’impression de la clé ou de la valeur avec l’itérateur i si sa valeur est égale à m.end (), sinon cela entraînerait une erreur de segmentation.
C++17
l'a simplifié un peu plus avec un If statement with initializer
. De cette façon, vous pouvez avoir votre gâteau et le manger aussi.
if ( auto it{ m.find( "key" ) }; it != std::end( m ) )
{
// Destructure the returned pair in to
// its sub components. Get them by reference.
// You can also get them by value.
auto&[ key, value ] { *it };
// Grab either the key or value stored in the pair.
// The key is stored in the 'first' variable and
// the 'value' is stored in the second.
auto& mkey{ it->first };
auto& mvalue{ it->second };
// That or just grab the entire pair pointed
// to by the iterator.
auto& pair{ *it };
}
else
{
// Key was not found..
}
En comparant le code de std :: map :: find et de std :: map :: count, je dirais que le premier peut générer un avantage en termes de performances:
const_iterator find(const key_type& _Keyval) const
{ // find an element in nonmutable sequence that matches _Keyval
const_iterator _Where = lower_bound(_Keyval); // Here one looks only for lower bound
return (_Where == end()
|| _DEBUG_LT_PRED(this->_Getcomp(),
_Keyval, this->_Key(_Where._Mynode()))
? end() : _Where);
}
size_type count(const key_type& _Keyval) const
{ // count all elements that match _Keyval
_Paircc _Ans = equal_range(_Keyval); // Here both lower and upper bounds are to be found, which is presumably slower.
size_type _Num = 0;
_Distance(_Ans.first, _Ans.second, _Num);
return (_Num);
}