codice:
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define MAX_STRING 55
#define MAX_LINE 512
typedef enum tagEnumStati
{
STATO_COGNOME,
STATO_MATRICOLA,
STATO_VOTO,
STATO_ERRORE
} EnumStati;
typedef struct tagStudenti
{
char Cognome[MAX_STRING];
int Matricola;
int Voto;
} Studenti;
int OttieniNumRecordsDaFileTesto(const char* szNomeFile)
{
FILE *fp;
char c;
int nCountRighe = 0;
fp = fopen(szNomeFile, "r");
if ( !fp )
{
printf("Errore nell'apertura del file %s\n", szNomeFile);
return 0;
}
while ( fread((void*)&c, 1, 1, fp) == 1 )
{
if ( c == '\n' )
{
nCountRighe++;
}
}
fclose(fp);
return nCountRighe - 1; /* -1 perchè la prima riga contiene i nomi dei campi */
}
int LeggiRecords(const char* szNomeFile, Studenti * pStud)
{
EnumStati stato = STATO_COGNOME;
int z = 0;
int nRec = 0;
FILE *fp;
char str[MAX_STRING];
char c;
/* Apriamo il file per la lettura */
fp = fopen(szNomeFile, "r");
if ( !fp )
{
printf("Errore nell'apertura del file\n");
return 0;
}
/* Saltiamo la prima riga perchè contiene i nomi dei campi */
while ( fread((void*)&c, 1, 1, fp) == 1 )
{
if ( c == '\n' )
break;
}
while ( fread((void*)&c, 1, 1, fp) == 1 )
{
if ( (c != '\r') && (c != '\n') && (c != ';') )
{
str[z++] = c;
}
else if ( c == ';' || c == '\n')
{
str[z] = '\0';
switch ( stato )
{
case STATO_COGNOME:
strcpy(pStud[nRec].Cognome, str);
stato = STATO_MATRICOLA;
printf("%s;", pStud[nRec].Cognome);
break;
case STATO_MATRICOLA:
pStud[nRec].Matricola = atoi(str);
stato = STATO_VOTO;
printf("%d;", pStud[nRec].Matricola);
break;
case STATO_VOTO:
pStud[nRec].Voto = atoi(str);
stato = STATO_COGNOME;
printf("%d\n", pStud[nRec].Voto);
break;
default:
stato = STATO_ERRORE;
break;
}
z = 0;
str[0] = '\0';
if ( c == '\n' )
nRec++;
}
}
fclose(fp);
fp = NULL;
return 1;
}
int ScriviRecords(const char* szNomeFile, const Studenti* pStud, int nRighe)
{
int y;
char *szNomiCampi = "Cognome;Matricola;Voto\n";
FILE *fp;
char str[MAX_LINE];
/* Apriamo il file per la scrittura */
fp = fopen(szNomeFile, "w");
if ( !fp )
{
printf("Errore nell'apertura del file %s\n", szNomeFile);
return 0;
}
/* La prima riga del file deve contenere i nomi dei campi */
fwrite(szNomiCampi, strlen(szNomiCampi), 1, fp);
/* Scriviamo i record nel file */
for (y = 0; y < nRighe; y++)
{
sprintf(str, "%s;%d;%d\n", pStud[y].Cognome, pStud[y].Matricola, pStud[y].Voto);
fwrite(str, strlen(str), 1, fp);
}
fclose(fp);
fp = NULL;
return 1;
}
void mergesort(Studenti *a, Studenti *b, int l, int r, int nOrdinaPer)
{
int i, j, k, m;
if ( r > l )
{
m = (r+l)/2;
mergesort(a, b, l, m, nOrdinaPer);
mergesort(a, b, m+1, r, nOrdinaPer);
for (i = m+1; i > l; i--)
b[i-1] = a[i-1];
for(j = m; j < r; j++)
b[r+m-j] = a[j+1];
switch ( nOrdinaPer )
{
case 'c':
case 'C':
for(k = l; k <= r; k++)
a[k] = (strcmp(b[i].Cognome, b[j].Cognome) < 0) ? b[i++] : b[j--];
break;
case 'm':
case 'M':
for(k = l; k <= r; k++)
{
if ( (b[i].Matricola < b[j].Matricola) )
a[k] = b[i++];
else if ( (b[i].Matricola > b[j].Matricola) )
a[k] = b[j--];
else
a[k] = (strcmp(b[i].Cognome, b[j].Cognome) < 0) ? b[i++] : b[j--];
}
break;
case 'v':
case 'V':
for(k = l; k <= r; k++)
if ( (b[i].Voto < b[j].Voto) )
a[k] = b[i++];
else if ( (b[i].Voto > b[j].Voto) )
a[k] = b[j--];
else
a[k] = (strcmp(b[i].Cognome, b[j].Cognome) < 0) ? b[i++] : b[j--];
break;
}
}
}
int main(void)
{
char *szNomeFileIn = "Studenti.txt";
char *szNomeFileOut = "StudentiOut.txt";
int c;
int NumRecords;
Studenti *pStud, *pStudTemp;
NumRecords = OttieniNumRecordsDaFileTesto(szNomeFileIn);
if ( NumRecords <= 0 )
{
printf("Il file %s non contiene records.", szNomeFileIn);
return -1;
}
pStud = malloc(NumRecords * sizeof(Studenti));
if(!pStud)
{
printf("Memoria insufficiente.\n");
return -1;
}
pStudTemp = malloc(NumRecords * sizeof(Studenti));
if(!pStudTemp)
{
printf("Memoria insufficiente.\n");
return -1;
}
if ( !LeggiRecords(szNomeFileIn, pStud) )
{
printf("Errore nella lettura dei records.\n");
return -1;
}
while ( 1 )
{
printf("\n\nInserisci una delle seguenti lettere:\n");
printf("C -> ordina per Cognome\n");
printf("M -> ordina per Matricola\n");
printf("V -> ordina per Voto\n");
printf("Una qualunque altra lettera per uscire.\n");
printf("Scelta: ");
fflush(stdin);
c = getchar();
mergesort(pStud, pStudTemp, 0, NumRecords-1, c);
if ( !ScriviRecords(szNomeFileOut, pStud, NumRecords) )
{
printf("Errore nella scrittura dei records.\n");
return -1;
}
else
{
switch ( c )
{
case 'c':
case 'C':
printf("I records, ordinati per cognome, sono stati scritti nel file %s\n", szNomeFileOut);
break;
case 'm':
case 'M':
printf("I records, ordinati per matricola, sono stati scritti nel file %s\n", szNomeFileOut);
break;
case 'v':
case 'V':
printf("I records, ordinati per voto, sono stati scritti nel file %s\n", szNomeFileOut);
break;
default:
return 0;
}
}
}
if ( pStud )
free(pStud);
if ( pStudTemp )
free(pStudTemp);
return 0;
}