Comment sortinger un tableau de structs en C?

J’ai un tableau des structures suivantes

typedef struct _my_data_ { unsigned int id; double latitude; double longitude; unsigned int content_len; char* name_dyn; char* descr_dyn; } mydata; 

et voudrait le sortinger ascendant par l’ ID . J’ai lu qu’il est possible de sortinger des tableaux à l’aide de la fonction qsort mais je ne sais pas comment l’utiliser correctement lors du sorting des structures.

Toute aide serait appréciée.

Vous avez besoin d’une fonction de comparaison de structure qui correspond au prototype de la fonction attendue par qsort() , à savoir:

 int md_comparator(const void *v1, const void *v2) { const mydata *p1 = (mydata *)v1; const mydata *p2 = (mydata *)v2; if (p1->id < p2->id) return -1; else if (p1->id > p2->id) return +1; else return 0; } 

Si vous arrivez à un critère de sorting plus complexe, cela rest une bonne base car vous pouvez append des critères secondaires en utilisant le même squelette:

 int md_comparator(const void *v1, const void *v2) { const mydata *p1 = (mydata *)v1; const mydata *p2 = (mydata *)v2; if (p1->latitude < p2->latitude) return -1; else if (p1->latitude > p2->latitude) return +1; else if (p1->longitude < p2->longitude) return -1; else if (p1->longitude > p2->longitude) return +1; else return 0; } 

Clairement, cela se répète pour autant de critères que vous avez besoin. Si vous avez besoin d’appeler une fonction ( strcmp() ?) Pour comparer des valeurs, appelez-la une fois mais affectez le retour à une variable locale et utilisez-la deux fois:

 int md_comparator(const void *v1, const void *v2) { const mydata *p1 = (mydata *)v1; const mydata *p2 = (mydata *)v2; int rc; if (p1->latitude < p2->latitude) return -1; else if (p1->latitude > p2->latitude) return +1; else if (p1->longitude < p2->longitude) return -1; else if (p1->longitude > p2->longitude) return +1; else if ((rc = strcmp(p1->name_dyn, p2->name_dyn)) < 0) return -1; else if (rc > 0) return +1; else return 0; } 

De plus, ce modèle fonctionne lorsque les membres de données sont des entiers non signés et évite les problèmes de débordement lors de la comparaison d’entiers signés. Notez que le raccourci que vous pouvez voir parfois, à savoir des variations sur:

 int md_comparator(const void *v1, const void *v2) /* BAD */ { /* BAD */ const mydata *p1 = (mydata *)v1; /* BAD */ const mydata *p2 = (mydata *)v2; /* BAD */ return(p1->id - p2->id); /* BAD */ } /* BAD */ 

is bad si id est non signé (la différence entre deux entiers non signés n’est jamais négatif) et peut être dépassé si les entiers sont signés et de grande ampleur et signes opposés.