Ciao, ho visto solo stasera il tuo post e quindi non so se ti è ancora utile la soluzione, ma siccome non
c'era niente in tv ho provato lo stesso a risolvere il tuo problema...
Ti allego il sorgente che dovrebbe ( se non ho capito male ) soddisfare la tua richiesta, anche se non ho
capito bene cosa intendevi con la frase: " L'ordinamento sulle chiavi secondarie
deve conservare l'ordine relativo prodotto dalla chiave primaria."
Be eventualmente rivedi il sorgente e correggilo tu !
Ciao!
    
#include <stdio.h>
#include <string.h> 
#include <stdlib.h> 
 /****************************/
    /* definizione di struttura */
    /****************************/
typedef struct tarchivio
{
	char cognomi[20];
	int matricole;
	int voti;
} archivio ;
//comparazione chiave primaria
int cognomi_cmp(archivio const * rec1,archivio const * rec2)
{
	return strcmp(rec1->cognomi,rec2->cognomi);	
}
//comparazione chiave matricola
int matricole_cmp(archivio const * rec1,archivio const * rec2)
{
	if ( rec1->matricole < rec2->matricole )
		return -1;
	if ( rec1->matricole > rec2->matricole )
		return 1;
	return 0;
}
//comparazione chiave voto
int voti_cmp(archivio const * rec1,archivio const * rec2)
{
	if ( rec1->voti < rec2->voti )
		return -1;
	if ( rec1->voti > rec2->voti )
		return 1;
	return 0;
}
void stampa(archivio * db, int dim)
{
	printf("***\n");
	for(int i=0; i<dim; i++)
		printf("%s %d %d\n", db[i].cognomi, db[i].matricole, db[i].voti);
	printf("\n");
}
const int ARCHIVIO_SIZE = 3;
/***********************************/
/* definizione della funzione main */
/***********************************/
int main(int argc, char* argv[])
{
   FILE *file_archivio; /* puntatore al file di input */
    archivio d[ARCHIVIO_SIZE], *p; /* input: struttura dati */
    int matricola_1, /* output: matricole */
        matricola_2,
        matricola_3;
    char cognome_1[20], /* output: cognomi */
         cognome_2[20],
         cognome_3[20];
    int voto_1, /* output: voti */
        voto_2,
        voto_3;
    int n = ARCHIVIO_SIZE; /* input: numero degli elementi array inizializzati */
    /* Apertura del file contenente i dati */
    file_archivio = fopen("archivio.csv", "r");
    /* acquisizione dei 10 cognomi con rispettive matricole e voti */
    fscanf(file_archivio, "%s %d %d", cognome_1, &matricola_1, &voto_1);
    fscanf(file_archivio, "%s %d %d", cognome_2, &matricola_2, &voto_2);
    fscanf(file_archivio, "%s %d %d", cognome_3, &matricola_3, &voto_3);
    /* assegnare ai campi delle strutture dichiarate i valori di fscanf */
    strcpy(d[0].cognomi, cognome_1);
           d[0].matricole = matricola_1;
           d[0].voti = voto_1;
    strcpy(d[1].cognomi, cognome_2);
           d[1].matricole = matricola_2;
           d[1].voti = voto_2;
    strcpy(d[2].cognomi, cognome_3);
           d[2].matricole = matricola_3;
           d[2].voti = voto_3;
    /*ciclo for per visualizzare gli elementi della struct */
    for(p = d; p < d+ARCHIVIO_SIZE; ++p)
		printf("%s %d %d\n", p->cognomi, p->matricole, p->voti);
	char scelta = argv[1][1]; //supponendo i parametri -c, -m, -v
	switch (scelta)
	{
		case 'c':
			qsort(d,ARCHIVIO_SIZE,sizeof(archivio),(int (*)(void const *,void const *))cognomi_cmp);
			stampa(d,n);
		break;
		case 'm':
			qsort(d,ARCHIVIO_SIZE,sizeof(archivio),(int (*)(void const *,void const *))matricole_cmp);		
			stampa(d,n);
		break;
		case 'v':
			qsort(d,ARCHIVIO_SIZE,sizeof(archivio),(int (*)(void const *,void const *))voti_cmp);		
			stampa(d,n);
		break;
	}
	return(0);
}