Per la questione dell'ordinamento, potresti "compattare" le date in un unico valore di tipo unsigned long per semplificare il confronto. Con l'operatore di scostamento bit e qualche cast è abbastanza semplice:
unsigned long data_in_unsigned_long( const evento *e ) {
unsigned long a = ((unsigned long)e->anno)<<16;
unsigned long m = ((unsigned long)e->mese)<<8;
unsigned long g = ((unsigned long)e->giorno);
return a | m | g;
}
Se non sei pratico dell'operatore di scostamento bit <<, in un esempio con data 20/2/2019 l'operazione provoca questo effetto:
2019 = 00000000 00000000 00000111 11100011
2 = 00000000 00000000 00000000 00000010
20 = 00000000 00000000 00000000 00010100
Scostando a sinistra l'anno 2019 di 16 bit con << si ottiene
prima: 00000000 00000000 00000111 11100011
dopo: 00000111 11100011 00000000 00000000
scostando a sinistra il mese 2 di 8 bit con << si ottiene
prima: 00000000 00000000 00000000 00000010
dopo: 00000000 00000000 00000010 00000000
il giorno 20 non serve scostarlo, per cui rimane com'e'
prima: 00000000 00000000 00000000 00010100
dopo: 00000000 00000000 00000000 00010100
A questo punto puoi "assemblare" i tre valori in un unico valore a 32 bit usando l'operatore |, che "accorpa" i bit precedentemente posizionati:
====== anno====== ==mese== =giorno=
00000111 11100011 00000010 00010100
Per confrontare le date in questo formato si possono usare i comuni operatori ==, <, >, <=, >= su un unico valore, il che è molto semplice.
Per poter usare qsort() dovrai predisporre una funzione "di servizio" della quale passerai poi il puntatore:
int confronta_eventi( const void *e1, const void *e2 ) {
unsigned long d1 = data_in_unsigned_long( e1 );
unsigned long d2 = data_in_unsigned_long( e2 );
return d1==d2 ? 0 : (d1<d2 ? -1 : 1);
}
In C *void è un puntatore generico, per cui puoi benissimo passarlo a data_in_unsigned_long() senza cast.
Alla fine della fiera, la chiamata a qsort() nel tuo main() si riduce a:
qsort( eventi, n, sizeof(*eventi), confronta_eventi );
Dunque, in questo esempio ti ho proposto:
1) cast di tipo
2) operatore di scostamento bit
3) operatore bit-a-bit | (or)
4) puntatori a void
5) operatore ternario ?:
6) qsort() (da stdlib.h)