2010-11-26 3 views
2

Je suis un programmeur Java et C#. Récemment, je travaille sur un projet C++. J'ai un problème de comment écrire l'exemple de code suivant en C++. Le code exemple suivant est pour trier une propriété d'un struct:Structure de tri basée sur une propriété de C++

public struct Person 
{ 
    public string name; 
    public int age; 
} 

Ajouter des personnes à une liste et trier l'âge:

static void main() 
{ 
    List<Person> persons = new List<Person>(); 

    Person person = new Person(); 
    person.age = 10; 
    person.name = "Jane"; 

    persons.Add(person); 

    person = new Person(); 
    person.age = 13; 
    person.name = "Jack"; 

    persons.Add(person); 

    person = new Person(); 
    person.age = 12; 
    person.name = "Anna"; 

    persons.Add(person); 

    // sort age 
    persons.Sort(delegate(Person p1, Person p2) 
    { return p1.age.CompareTo(p2.age); }); 

    persons.ForEach(delegate(Person p) 
    { Console.WriteLine(String.Format("{0} {1}", p.age, p.name)); }); 
} 

Comment puis-je écrire un code d'échantillon équivalent en C++?

Répondre

8

Compte tenu du type Person:

struct Person 
{ 
    Person(int age_, const std::string &name_) 
     : age(age_), name(name_) 
    {} 

    int age; 
    std::string name; 
}; 

int main() 
{ 
    std::list<Person> persons; 
    persons.push_back(Person(10, "Jane")); 
    persons.push_back(Person(13, "Jack")); 
    persons.push_back(Person(12, "Anna")); 
} 

Solution 1

bool compareAge(const Person &lhs, const Person &rhs) 
{ 
    return lhs.age < rhs.age; 
} 

int main() 
{ 
    /* persons list initialization */ 
    persons.sort(&compareAge); 
} 

Solution 2 (en utilisant boost::bind)

int main() 
{ 
    /* persons list initialization */ 
    persons.sort(boost::bind(&Person::age, _1) < boost::bind(&Person::age, _2)); 
} 

Là aussi est une solution utilisant C++0x lambdas.

+0

Bonjour icecime, merci beaucoup pour vos solutions. J'ai vérifié les deux solutions mais la solution 2 est capable de compiler mais la solution 1 ne l'est pas. Je préfère toujours la première solution cependant. L'erreur de la première solution est la suivante: ISO C++ interdit de prendre l'adresse d'une fonction membre non statique ou parenthésée non statique pour former un pointeur vers la fonction membre. Dites '& XXX: compareAge'. – olidev

+0

@JoesyXHN: c'est parce que vous avez ajouté 'compareAge' * dans la classe' Person', alors que je l'ai défini comme une fonction libre (* en dehors de la classe). – icecrime

+0

oui, la solution 2 fonctionne parfaitement. Cependant, je voudrais savoir une méthode de comparaison normale de la solution 1. Cela ne fonctionne pas pour moi. Si je déclare à l'extérieur, je dois déclarer la structure comme publique. Mais c'est privé dans notre cas. De plus, j'ai essayé de le rendre public mais j'ai ensuite eu ce problème: Utilisation invalide du type incomplet 'const struct xxx: yyy: Person'. Je l'ai déjà déclaré comme une méthode gratuite. Merci d'avance – olidev

1

Une autre option que vous avez (au lieu d'utiliser la liste et de la réorganiser selon certains critères) pourrait utiliser std::map (ou std::multimap).

Lorsqu'ils sont placés dans map, ils sont classés par le key. std::map nécessite une clé unique, tandis que std::multimap peut contenir plusieurs éléments avec la même clé.

// multimap< key, value > 
std::multimap< int, Person* > IntOrderedMap; 

IntOrderedMap ageOrder; 

Person* p = new Person("Jack", 13); 
ageOrder.insert(std::make_pair(p->age, p)); // use age as the map key 

p = new Person("Mike", 12); 
ageOrder.insert(std::make_pair(p->age, p)); 

p = new Person("Paul", 13); 
ageOrder.insert(std::make_pair(p->age, p)); 

Ensuite, vous pouvez le parcourir, les éléments sont commandés par la clé (âge)

for(IntOrderedMap::const_iterator it = ageOrder.begin(); it != ageOrder.end(); ++it) 
{ 
    std::cout << it->second->Name << " is " << it->first << " years old" << std::endl; 
} 

Sortie:

Mike is 12 years old 
Jack is 13 years old 
Paul is 13 years old 

Cela vous permet en même temps d'avoir un autre récipient où les personnes sont classées par nom.

std::multimap nameOrder; 
for(IntOrderedMap::const_iterator it = ageOrder.begin(); it != ageOrder.end(); ++it) 
{ 
    Person* p = it->second; 
    nameOrder.insert(std::make_pair(p->name, p); 
} 
+0

cette solution n'est bonne que si vous êtes sûr que vous avez besoin de les trier seulement par âge –

+0

@wiso Je viens d'ajouter un exemple montrant que l'utilisation de la carte donne d'autres options –

+0

Ceci est également une bonne solution. Mais je préfère utiliser la méthode de comparaison normale ou utiliser le Boost! Merci! – olidev

Questions connexes