J'écris un code de tri dans une bibliothèque existante, donc je ne peux pas apporter de modifications dans le modèle de données J'ai ce qui suit

 class Point
 {

   //Some functions 
   public:
       float x, y, z;

  };

int less_than_key (const void *arg1, const void *arg2)
 {

      Point *r1 = (Point*) arg1;
      Point *r2 = (Point*) arg2;

      if(r1->z < r2->z )
        return -1;

     else if(r1->z > r2->z )
       return 1;
    else
       return 0;
}

int main()
{
   list<Point> myPoints; 

    Point p;
    p.x = 0;
    p.y = 0;
    p.z = 0;
    myPoints.push_back(p);

    p.x = 0;
    p.y = 0;
    p.z = 6;
    myPoints.push_back(p);

    p.x = 0;
    p.y = 0;
    p.z = 2;
    myPoints.push_back(p);

    for(int i=0; i<myPoints.size(); i++)
      cout<<" Point "<<p[i].x<<", "<<p[i].y<<", "<<p[i].z<<"\n";

    qsort(&myPoints, myPoints.size(), sizeof(Point), less_than_key);

    for(int i=0; i<myPoints.size(); i++)
      cout<<"Point "<<p[i].x<<", "<<p[i].y<<", "<<p[i].z<<"\n";
 }

Je veux trier les objets en fonction de la valeur z. La sortie que j'attends est la suivante

 Before sorting 
 Point 0, 0, 0
 Point 0, 0, 6
 Point 0, 0, 2

 After sorting 
 Point 0, 0, 0
 Point 0, 0, 2
 Point 0, 0, 6

Lorsque j'exécute le code suivant, il se bloque pendant l'appel de tri et j'obtiens l'erreur suivante

  terminated with signal 11

J'ai lu dans d'autres solutions que je devrais passer la liste comme suit

   qsort(&myPoints[0], myPoints.size(), sizeof(Point), less_than_key);

Mais quand j'essaye de le compiler, j'obtiens ce qui suit

  no match for 'operator[]' (operand types are 'std::list<Point>' and 'int')
0
Lily 3 août 2017 à 21:32

2 réponses

Meilleure réponse

Vous pouvez utiliser std :: sort avec une expression lambda, voici un exemple:

#include <algorithm>

std::list<Point> myPoints;

//adding points to list...

std::sort(myPoints.begin(), myPoints.end(), [](const Point& lhs, const Point& rhs)
{
   return lhs.z < rhs.z;
});

for(int i=0; i<myPoints.size(); i++)
  cout<<"Point "<<p[i].x<<", "<<p[i].y<<", "<<p[i].z<<"\n";

Le code ci-dessus triera, puis imprimera une liste triée de points

2
morsisko 3 août 2017 à 18:48

qsort est de la vieille école C. Il attend 4 paramètres:

ptr - pointeur vers le tableau à trier

count - nombre d'éléments dans le tableau

size - taille de chaque élément du tableau en octets

comp - fonction de comparaison qui renvoie une valeur entière négative si le premier argument est inférieur au second, une valeur entière positive si le premier argument est supérieur au second et zéro si les arguments sont égaux.

de std::qsort

Ce qui a été donné est

  • pointeur vers un list
  • nombre d'éléments dans le tableau
  • taille de chaque élément du tableau en octets
  • Fonction de comparaison

C'est le pointeur vers list qui vous tue. Je soupçonne que c'est un std::list, mais je ne peux pas le prouver. Quoi qu'il en soit, il s'agit d'une structure de données basée sur un modèle et cela rend les choses velues. Ce n'est PAS un tableau et ne doit pas être utilisé comme un tableau.

qsort a essayé de l'utiliser comme tableau et de citer Dune:

Ils ont essayé et échoué?

Ils ont essayé et sont morts.

Maintenant, pour tout ce que nous savons, list pourrait être une structure très simple qui contient un tableau de Point parfaitement positionné pour s'aligner avec le début de l'instance - l'adresse du tableau contenu est la même que l'adresse du list instancié - mais le crash suggère le contraire.

Et si list est un tableau dynamique (suggéré par son utilisation) ou une liste liée (suggérée par le nom et l'utilisation), alors une instance list ne contient même pas ses données. Il contient un pointeur vers les données. Il n'y a pas de tableau à utiliser pour qsort et il parcourra rapidement le peu de données stockées dans list, de l'autre côté et dans le monde sauvage et farfelu de Comportement non défini. Cela dit, l'instance que vous avez passée un non-tableau dans qsort vous avez déjà atteint le comportement indéfini.

La solution consiste à utiliser intégré std::sort si {{ X1}} a une interface d'itérateur. si list est vraiment std::list, il peut y avoir des avantages en termes de performances en utilisant std::list::sort. Si ni l'un ni l'autre n'est vrai et que list est une classe personnalisée malheureusement nommée, vous devrez écrire votre propre routine de tri (ou faire la chose intelligente et jeter la classe personnalisée en faveur d'un conteneur de bibliothèque).

0
user4581301 3 août 2017 à 19:22