N.F.I. 2 ième année |
Langage C |
décembre 1999 |
Corrigé de décembre 1999
Dans la programmation qui suit, les saisies sont supposées faites sans erreur.
#include
#include
#include
#define NOMFIC "lesMatieresNotes"
#define MAX_NB_M 20 /* Maximum du nombre de matières */
#define MAX_LG_NOM_M 50 /* Maximum longueur d'un nom de matières */
#define MAX_NB_E 100 /* Maximum du nombre d'élèves */
typedef char NomM[MAX_LG_NOM_M+1];/* Mémorise un nom de matière (forme chaîne)*/
Question 1
/* Lit une ligne du fichier logique fic, ouvert sur un fichier physique
structuré comme lesMatieresNotes, et fournit: le numéro d'étudiant (*pnumE),
le trimestre (*pnumT), la matière (nm) et la note (*pnote).
La valeur renvoyée est: + 0 si la fin de fichier a été dépassée,
+ une valeur non nulle sinon
Il n'y a pas de vérification sur la structure des lignes.
*/
int uneLigne(FILE *fic, int *pnumE, int * pnumT, NomM nm, double * pnote) {
char c1,c2,c3,c4,c5; int i;
fscanf(fic,"%c%d%c%d%c", &c1,pnumE,&c2,pnumT,&c3);
if(feof(fic)) return 1;
/* Mémoriser les caractères jusqu'à '|' */
i=-1;
do { i++; nm[i]=fgetc(fic);} while( nm[i]!='|');
nm[i]='\0';
/* Lire un séparateur, une note, un séparateur et R/C */
fscanf(fic,"%le%c%c", pnote,&c4,&c5);
return(feof(fic));
}
Question 2
/* Recherche du nom de matière intit dans le tableau de matières tnm;
dans tmn la dernière matière est suivie d'une chaîne vide.
Renvoie : + le plus petit indice i tel que tnm[i] soit identique à intit
+ -1 si intit ne figure pas dans le tableau
*/
int dansTabNomM(NomM tnm[], NomM intit) {
int n, trouve;
n=0; trouve=0;
/* on arrête si on a trouvé intit (trouve=1) ou si on est sur la dernière
chaîne (chaîne vide: tnm[n][0]=='\0' )
*/
while( !trouve && tnm[n][0]!= '\0') {
if( strcmp(tnm[n],intit) ) n++;
else trouve=1;
}
return ( trouve ) ? n : -1;
}
Question 3
/* Extrait les noms de matières du fichier nomfic, structuré comme le
fichier lesMatieresNotes, et les mémorise dans le tableau tnm.
Renvoie le nombre de matières, ou -1 si le fichier n'a pu être trouvé.
Utilise le sous-programme uneLigne .
*/
int nomsMatieres( char nomfic[], NomM tnm[]){
FILE *ficMN = fopen(nomfic,"rt");
int numE, numT, finfic; NomM intit; double note;
int k, nbM;
if(ficMN==NULL) { fclose(ficMN); return -1; }
/* Parcours du fichier; sur chaque ligne, le nom de matière est mémorisé, s'il
ne figure pas déjà dans tnm.
Pour conserver la structure de tnm, nécessaire pour l'appel de dansTabNomM,
on place une chaîne vide après toute chaîne ajoutée.
*/
nbM=0; strcpy(tnm[nbM],"");
finfic=uneLigne(ficMN,&numE,&numT,intit,¬e);
while(!finfic) {
k =dansTabNomM(tnm,intit);
/* printf("nbM=%d nomM:%s k:%d\n", nbM, intit, k); */
if( k==-1 ){ /* Une matière pas encore rencontrée */
strcpy(tnm[nbM], intit); /* est ajoutée à tnm */
nbM++;
strcpy(tnm[nbM],""); /* on ajoute la chîne vide */
}
/* On tente de lire la ligne suivante */
finfic = uneLigne(ficMN,&numE,&numT,intit,¬e);
}
fclose(ficMN);
return nbM;
}
Question 4
int main( int nbm, char * mots[]) {
char nomfic[] = NOMFIC;
int tri = nbm < 2 ? 3 : atoi(mots[1]);
FILE *ficMN = fopen(nomfic,"rt"); int finfic, numF;
int numE, numT; NomM intit; double note;
double notesT[MAX_NB_E][MAX_NB_M]; /* les notes du trimestre */
int numET[MAX_NB_E]; int nbET; /* tableau des numéros d'étudiants */
NomM nomMT[MAX_NB_M+1]; int nbMT; /* tableau des matières du trimestre */
int i, inotes, jnotes, kM;
if(ficMN == NULL) { printf("Fichier introuvable :'%s'\n", nomfic); return 1;}
/* Les numéros des étudiants sont mémorisés dans numET à leur première
apparition; pour repérer cette première apparition on initialise numET à -1,
qui est une valeur ne pouvant être confondue avec un numéro.
*/
for( i=0; i < MAX_NB_E; i++) numET[i]=-1;
/* Parcours, par ligne, du fichier lesMatieresNotes
jnotes est l'indice de la colonne du tableau notes, où sont mémorisées les
les notes d'une matière; d'après la constitution du fichier, toutes
les notes d'une matière dans un trimestre donné sont consécutives.
inotes est l'indice de la ligne où sont mémorisées les notes d' un étudiant
*/
jnotes=-1; inotes=-1;
numF=0; /* numéro de ligne courante dans le fichier, utilisé uniquement
pour repérer la ligne où une erreur est rencontrée */
finfic=uneLigne(ficMN,&numE,&numT,intit,¬e);
while(!finfic) {
numF ++; /* nouvelle ligne dans le fichier; */
if (numT == tri ) {
kM = dansTabNomM(nomMT,intit);
/* matière a-t-elle été rencontrée? */
if (kM == -1) { /* nouvelle matière:
on ajoute une colonne,
on repart première ligne et
on mémorise le nom de la matière */
inotes=0; jnotes++;
strcpy(nomMT[jnotes], intit); strcpy(nomMT[jnotes+1],"");
}
else { /* nouvel étudiant dans la même matière */
inotes++;
}
if(numET[inotes] == -1) numET[inotes]=numE;
else if(numET[inotes] != numE)
printf("\nErreur ligne %d \n", numF);
/* printf("\nligne:%d, numE:%d iM:%d kM:%d\n", numF, numE, iM,kM); */
notesT[inotes][jnotes]=note;
}
finfic=uneLigne(ficMN,&numE,&numT,intit,¬e);
}
fclose(ficMN);
nbET = inotes + 1; /* nombre d'étudiants ce trimestre */
nbMT = jnotes + 1; /* nombre de matières ce trimestre */
printf("\nMatières du trimestre %d: ", tri);
for( jnotes = 0; jnotes < nbMT; jnotes++) printf("%12s",nomMT[jnotes]);
for( inotes = 0; inotes < nbET; inotes++) {
printf("\n%20d", numET[inotes]);
for(jnotes=0; jnotes<nbMT; jnotes++)
printf("%12.2f",notesT[inotes][jnotes]);
}
printf("\n");
}