Question

j'ai une structure:

struct pkt_
{
  double x;
  double y;
  double alfa;
  double r_kw;
};

typedef struct pkt_ pkt;

Un tableau de ces structures:

pkt *tab_pkt;

tab_pkt = malloc(ilosc_pkt * sizeof(pkt));

Ce que je veux faire est de trier tab_pkt par tab_pkt.alfa et tab_pkt.r :

qsort(tab_pkt, ilosc_pkt, sizeof(pkt), porownaj);

Où porownaj est une fonction de comparaison, mais comment l’écrire? Voici mon " sketch " de celui-ci:

int porownaj(const void *pkt_a, const void *pkt_b)
{
  if (pkt_a.alfa > pkt_b.alfa && pkt_a.r_kw > pkt_b.r_kw) return 1;
  if (pkt_a.alfa == pkt_b.alfa && pkt_a.r_kw == pkt_b.r_kw) return 0;
  if (pkt_a.alfa < pkt_b.alfa && pkt_a.r_kw < pkt_b.r_kw) return -1;
}
Était-ce utile?

La solution

Quelque chose comme ça devrait marcher:

int porownaj(const void *p_a, const void *p_b)
{
  /* Need to store arguments in appropriate type before using */
  const pkt *pkt_a = p_a;
  const pkt *pkt_b = p_b;

  /* Return 1 or -1 if alfa members are not equal */
  if (pkt_a->alfa > pkt_b->alfa) return 1;
  if (pkt_a->alfa < pkt_b->alfa) return -1;

  /* If alfa members are equal return 1 or -1 if r_kw members not equal */
  if (pkt_a->r_kw > pkt_b->r_kw) return 1;
  if (pkt_a->r_kw < pkt_b->r_kw) return -1;

  /* Return 0 if both members are equal in both structures */
  return 0;
}

Éloignez-vous des astuces idiotes telles que:

return pkt_a->r_kw - pkt_b->r_kw;

qui renvoient des valeurs non normalisées, sont difficiles à lire, ne fonctionnent pas correctement pour les nombres à virgule flottante et ont parfois des casse-tête difficiles qui ne fonctionnent pas correctement, même pour les valeurs entières.

Autres conseils

Le problème comporte deux parties: comment écrire le code et comparer les types de paquets. Vous devez vous assurer de toujours renvoyer une valeur. Votre code doit également toujours être tel que:

porownaj(&pkt_a, &pkt_b) == -porownaj(&pkt_b, &pkt_a)

Votre comparaison hiérarchique ne traite pas les cas tels que:

pkt_a->alfa >  pkt_b->alfa && pkt_a->r_kw <= pkt_b->r_kw
pkt_a->alfa <  pkt_b->alfa && pkt_a->r_kw >= pkt_b->r_kw
pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw != pkt_b->r_kw

Il y a encore un problème - est-il approprié de comparer les valeurs à virgule flottante pour une égalité exacte? Cela dépendra de votre application.

Mécaniquement, vous devez convertir les pointeurs const void en pointeurs de structure const. J'utilise la conversion explicite - C ++ le requiert et j'essaie de rendre mon code acceptable pour un compilateur C ++, même s'il s'agit réellement de code C.

int porownaj(const void *vp1, const void *vp2)
{
     const pkt *pkt_a = (const pkt *)vp1;
     const pkt *pkt_b = (const pkt *)vp2;

     if (pkt_a->alfa >  pkt_b->alfa && pkt_a->r_kw >  pkt_b->r_kw) return 1;
     if (pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw == pkt_b->r_kw) return 0;
     if (pkt_a->alfa <  pkt_b->alfa && pkt_a->r_kw <  pkt_b->r_kw) return -1;
     return 0;
 }

Ceci ne traite pas les bits que je ne peux pas résoudre car je ne suis pas partie aux informations nécessaires. Notez qu'en général, les objets multidimensionnels (tels que les nombres complexes, les coordonnées (x, y) ou (x, y, z)) ne peuvent pas simplement être comparés à des valeurs supérieures ou inférieures ou égales à.

Oui, je trie par alfa et r_kw décide si pkt est premier (la première valeur aura le plus grand (ou le plus petit) alfa et r_kw je pense). C'est comme ça que je comprends le problème, je ne suis pas sûr à 100%.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top