Correction examen asd1 mpi janvier 2016 fonctions et gestion
Télécharger PDFCorrection Examen ASD1 MPI Janvier 2016
Exercice 1 : Algorithmique
Fonction est_premier(n : entier) : booléen
Cette fonction détermine si un nombre entier `n` est premier. Elle teste la divisibilité de `n` par tous les entiers de 2 jusqu'à `n/2`. Si un diviseur est trouvé, le nombre n'est pas premier (retourne vrai, ce qui est une erreur logique dans le pseudo-code, cela devrait retourner faux). Si aucun diviseur n'est trouvé après avoir parcouru toutes les possibilités, le nombre est premier (retourne faux, ce qui devrait être vrai).
Pour être logiquement correct, la ligne retourner (vrai) devrait être retourner faux et la ligne Retourner(faux) devrait être Retourner vrai.
Pseudo-code original :
Fonction est_premier(n :entier) : booléen
Var i : entier
Début
i<-2
Tantque(i<=n/2)
si (n Mod i =0) alors
retourner vrai
finsi
i<-i+1
FinTantque
Retourner faux ;
Fin
Fonction SuperPremier(n : entier) : booléen
Cette fonction vérifie si un nombre `n` peut être considéré comme "Super Premier" selon une définition spécifique. Elle itère en augmentant `i` par des puissances de 10 (1, 10, 100, etc.) tant que la division entière de `n` par `i` est supérieure à zéro. À chaque itération, elle appelle la fonction `est_premier` sur le reste de la division de `n` par `i` (`n Mod i`). Si l'un de ces restes n'est pas premier, la fonction retourne faux. Si tous les restes sont premiers, elle retourne vrai.
Pseudo-code original :
Fonction SuperPremier(n :entier) : booléen
Var i : entier
Début
i<-1
Tantque(n div i >0)
si (est_premier(n Mod i) =faux) alors
retourner faux
finsi
i<-i*10
FinTantque
Retourner vrai ;
Fin
Exercice 2 : Programmation en C
1) int compare_date(char *date1, char *date2)
Cette fonction compare deux dates fournies sous forme de chaînes de caractères. Elle utilise `sscanf` pour extraire le jour (j), le mois (m) et l'année (a) de chaque date. Ensuite, elle convertit chaque date en un entier unique au format `AAAAJJMM` (année*10000 + mois*100 + jour) pour faciliter la comparaison. La fonction retourne la différence entre la première et la deuxième date convertie en entier, ce qui permet de savoir quelle date est antérieure ou postérieure.
Code C :
int compare_date(char *date1, char *date2){
int j,m,a,d1,d2;
sscanf(date1,"%d%*c%d%*c%d",&j,&m,&a);
d1=a*10000+m*100+j;
sscanf(date2,"%d%*c%d%*c%d",&j,&m,&a);
d2=a*10000+m*100+j;
return(d1-d2);
}
2) int nb_ligne_dans_mvt (FILE *fp_mvt)
Cette fonction calcule le nombre de lignes (ou enregistrements) dans un fichier de mouvements (`fp_mvt`). Elle positionne le pointeur de fichier à la fin du fichier (`fseek(fp,0L,SEEK_END)`) et utilise `ftell` pour obtenir la taille totale du fichier en octets. En supposant que chaque ligne (enregistrement) a une taille fixe de 42 octets, elle divise la taille totale par 42 pour obtenir le nombre de lignes.
Code C :
int nb_ligne_dans_mvt (FILE *fp_mvt){
fseek(fp,0L,SEEK_END) ;
return(ftell(fp)/42) ;
}
3) int seek_compte (FILE *fp_compte, int num_compte, char *ligne_compte)
Cette fonction recherche un numéro de compte spécifique (`num_compte`) dans un fichier de comptes (`fp_compte`). Elle réinitialise le pointeur du fichier au début (`rewind`) puis lit chaque ligne du fichier. Pour chaque ligne, elle extrait le numéro de compte en utilisant `sscanf`. Si le numéro de compte correspond, la fonction retourne 1 et la ligne du compte est copiée dans `ligne_compte`. Si le compte n'est pas trouvé après avoir parcouru tout le fichier, elle retourne 0 et `ligne_compte` est vide.
Code C :
int seek_compte (FILE *fp_compte, int num_compte, char *ligne_compte){
int num;
rewind(fp_compte);
while(fgets(ligne_compte,60,fp_compte)) {
sscanf(ligne_compte,"%6d",&num);
if (num==num_compte) return 1;
}
*ligne_compte='\0' ;
return 0;
}
4) int seek_premier_mvt(FILE *fp_compte, FILE *fp_mvt, int num_compte, char *ligne_mvt)
Cette fonction cherche le premier mouvement associé à un numéro de compte donné (`num_compte`). Elle commence par appeler `seek_compte` pour trouver la ligne correspondant au compte. Si le compte est trouvé, elle extrait un numéro de ligne de premier mouvement (`premier`) à partir de la ligne du compte (à l'offset 50). Si ce numéro est valide (différent de -1), elle utilise `fseek` pour se positionner directement au début du premier mouvement dans le fichier de mouvements (`fp_mvt`) et lit cette ligne dans `ligne_mvt`, puis retourne 1. Sinon, ou si le compte n'est pas trouvé, elle retourne 0.
Code C :
int seek_premier_mvt(FILE *fp_compte, FILE *fp_mvt, int num_compte,char *ligne_mvt){
char s[100];
int premier;
if(seek_compte(fp_compte, num_compte, s)) {
sscanf(s+50,"4%d",premier);
if(premier!=-1) {
fseek(fp_mvt,(premier-1)*42,SEEK_SET);
fgets(ligne_mvt,50,fp_mvt);
return(1);
} else return(0);
}
return(0);
}
5) void extrait (FILE *fp_mvt, int num_compte, int num_ligne)
Cette fonction récursive est conçue pour extraire et afficher les mouvements d'un compte donné, du plus récent au plus ancien. Elle fonctionne en deux phases :
- Cas de base (`num_ligne == -1`) : Lorsque tous les mouvements ont été traités (ou lors de l'appel initial si `num_ligne` est un indicateur spécial), elle recherche et affiche les informations du compte.
- Cas récursif (`num_ligne != -1`) : Elle se positionne sur la ligne du mouvement spécifiée par `num_ligne` dans le fichier des mouvements. Elle extrait ensuite le numéro de la ligne suivante (`numNext`) à partir de cette ligne et effectue un appel récursif pour traiter le mouvement suivant (plus récent). Après le retour de l'appel récursif (ce qui signifie que les mouvements plus récents ont déjà été affichés), elle extrait les détails du mouvement actuel (date, montant, description) et les affiche. Cette approche garantit un affichage du plus récent au plus ancien grâce à la nature de la récursion.
Code C :
void extrait (FILE *fp_mvt, int num_compte, int num_ligne){
FILE *fp=fopen("Compte.txt","r");
char ligne_compte[70],ligne_mvt[50],dateop[15],desop[15];
int numNext;
float mnt;
if (num_ligne==-1) {
// Lorsqu'on a parcouru tous les comptes on arrive à 1 et on affiche l'en-tête
seek_compte(fp,num_compte,ligne_compte);
afficher_compte(ligne_compte);
} else {
// on extrait le mvt de cette ligne
fseek(fp_mvt,(num_ligne-1)*42,SEEK_SET);
fgets(ligne_mvt,50,ligne_mvt);
// on extrait le num de la ligne suivante
sscanf(ligne_mvt+37,"%4d",&numNext);
// Appel récursif
extrait(fp_mvt,num_compte,numNext);
// Puisqu'on veut afficher du plus récent au plus ancien et que
// dans le fichier le plus récent vient en dernier, on affiche après
// l'appel récursif
sscanf(s+6,"%10s%10f%*c%10s",dateop,mnt,desop);
printf("%s %s %f\n",dateop,desop,mnt);
}
}
Foire Aux Questions (FAQ)
Q1: Quel est le rôle de la fonction est_premier dans l'Exercice 1 ?
A1: La fonction est_premier a pour but de vérifier si un nombre entier donné est un nombre premier. Elle parcourt les diviseurs potentiels pour déterminer s'il est divisible uniquement par 1 et lui-même (avec une correction logique à appliquer pour un fonctionnement correct).
Q2: Comment la fonction compare_date gère-t-elle la comparaison de dates ?
A2: La fonction compare_date convertit chaque date de format chaîne en un entier unique (format AAAAJJMM). Cette conversion permet une comparaison simple et directe des dates en soustrayant les deux entiers résultants, indiquant ainsi laquelle des deux dates est antérieure ou postérieure.
Q3: Quel est le principe de la fonction récursive extrait pour l'affichage des mouvements ?
A3: La fonction extrait utilise la récursion pour afficher les mouvements d'un compte du plus récent au plus ancien. Elle appelle récursivement la fonction pour les mouvements "suivants" (plus récents) avant d'afficher les détails du mouvement "actuel". Cela assure que l'affichage des mouvements se fait dans l'ordre chronologique inverse de leur stockage dans le fichier.