2009-12-07 16 views
1

J'ai fait une méthode pour faire défiler/encapsuler une carte d'éléments, de sorte que si la fin est atteinte, la méthode renvoie le premier élément et vice-versa.C++ "Défilement" dans les éléments d'un fichier stl :: map

Y at-il une façon plus succincte de le faire?

MyMap::const_iterator it = myMap.find(myKey); 

if (it == myMap.end()) 
    return 0; 

if (forward) { 

    it++; 

    if (it == myMap.end()) { 
     it = myMap.begin(); 
    } 

} else { 

    if (it == myMap.begin()) { 
     it = myMap.end(); 
    } 

    it--; 

} 

Répondre

1

Vous pouvez le faire avec un modèle. Comme cela a été indiqué par une affiche précédente, cela peut être lourd du point de vue qu'il n'atteint jamais la fin, de sorte que l'utilisateur doit en quelque sorte contrôler cela. Je suppose que vous avez une bonne raison, peut-être en produisant un comportement de tournoi à la ronde.

#include <iostream> 
#include <string> 
#include <vector> 
#include <set> 
#include <map> 

using namespace std; 

template <class T> 
class ScrollIterator 
{ 
public: 
    ScrollIterator(T &myCtr, typename T::iterator pos) 
     :ctr(myCtr), 
     it(pos) 
    { 

    } 

    ScrollIterator operator++() 
    { 
     if (++it == ctr.end()) { it = ctr.begin(); } 
     return *this; 
    } 

    bool operator!=(const ScrollIterator &rhs) const 
    { 
     return (this->it != rhs.it); 
    } 

    bool operator!=(const typename T::const_iterator &rhsIT) const 
    { 
     return (this->it != rhsIT); 
    } 

    typename T::value_type operator*() const 
    { 
     return *it; 
    } 

private: 
    T &ctr; 
    typename T::iterator it; 
}; 


int main (int argc, char *argv[]) 
{ 
    vector<int> v; 
    v.push_back(2); 
    v.push_back(3); 
    v.push_back(5); 
    v.push_back(7); 

    int i = 0; 
    for (ScrollIterator<vector<int> > it(v,v.begin()); it != v.end() && i < 10; ++i, ++it) 
    { 
     cout << "Vector = " << i << " Value: " << *it << "\n"; 
    } 

    set<string> s; 
    s.insert("c"); 
    s.insert("a"); 
    s.insert("b"); 

    i = 0; 
    for (ScrollIterator<set<string> > it(s,s.begin()); it != s.end() && i < 10; ++i, ++it) 
    { 
     cout << "Set = " << i << " Value: " << *it << "\n"; 
    } 

    map<string, int> y; 
    y["z"] = 10; 
    y["y"] = 20; 
    y["x"] = 30; 

    i = 0; 
    for (ScrollIterator<map<string, int> > it(y,y.begin()); it != y.end() && i < 10; ++i, ++it) 
    { 
     cout << "Map = " << i << " Iterator: " << (*it).first << " = " << (*it).second << "\n"; 
    } 

    return 1; 
} 
5

Vous pouvez mettre en œuvre le comportement enveloppant directement dans une nouvelle iterator classe - basé sur un modèle à une enveloppe pour une iterator réelle, qui fournit une interface plus élégante à l'appelant (de sorte que ses opérateurs d'incrémentation et de décrémentation faire le wrap-around automatiquement).

Egalement - faites attention au récipient vide. Vous ne voulez pas "wrap-around" quand il n'y a pas d'éléments dans le conteneur.

1

Vous pouvez utiliser upper_bound et lower_bound. Par exemple:

if (myMap.empty()) return 0; 

MyMap::const_iterator it; 

if (forward) { 
    it = myMap.upper_bound(myKey); 
    if (it == myMap.end()) it = myMap.begin(); 
} else { 
    it = myMap.lower_bound(myKey); 
    if (it == myMap.begin()) it = myMap.end(); 
    --it; 
} 

Ceci se comportera également différemment si "myKey" n'existe pas dans la carte. Cela reprendra d'où la clé aurait été plutôt que d'aller à la fin ou au début.

0

Ceci est une conception difficile. Si l'atteinte de la «fin» se termine autour du «début», comment représentez-vous un contenant vide? L'idée enveloppante modélise une séquence infinie ou un anneau, mais sans moyen de détecter si l'itérateur pointe toujours vers une position valide. Ce problème n'est pas sans rappeler les tentatives d'écriture d'une mémoire tampon circulaire de taille variable (comme une file d'attente) sans utiliser une "entrée fictive": comment distinguer une sonnerie vide d'une sonnerie complète? Le stockage d'une position de base et d'une taille est uniquement approprié pour le stockage à accès aléatoire (par opposition aux nœuds liés) et est moins favorable à l'optimisation du verrouillage que les paires pointeur ou index.

+0

Une entrée fictive ici serait évidemment 'map.end()'. –