¿Cómo ordenar una matriz de estructuras en C?

Tengo una serie de las siguientes estructuras

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

y me gustaría ordenarlo ascendiendo por ID . Leí que es posible ordenar matrices utilizando la función qsort , pero no estoy seguro de cómo usarla correctamente al ordenar las estructuras.

Cualquier ayuda sería apreciada.

Necesita una función de comparador de estructuras que coincida con el prototipo de la función esperada por qsort() , a saber:

 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 alguna vez llega a un criterio de clasificación más complejo, esta sigue siendo una buena base porque puede agregar criterios secundarios usando el mismo esqueleto:

 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; } 

Claramente, esto se repite para todos los criterios que necesite. Si necesita llamar a una función ( strcmp() ?) Para comparar valores, strcmp() una vez pero asigne el retorno a una variable local y utilícelo dos veces:

 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; } 

Además, esta plantilla funciona cuando los miembros de datos son enteros sin signo, y evita problemas de desbordamiento al comparar enteros con signo. Tenga en cuenta que el atajo que a veces puede ver, es decir, variaciones en:

 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 */ 

es malo si id no está firmado (la diferencia de dos enteros sin signo nunca es negativo), y está sujeto a desbordamiento si los enteros están firmados y de gran magnitud y signos opuestos.