1ère année Informatique.
Najib Tounsi
Sommaire
Soit un fichier d'articles de commerce ayant pour structure
typedef struct {
int numero;
char nom[20];
float prixHT;
int qte;
} TYPEART;
TYPEART article;
déclaré comme suit:
FILE *farticle;
Créer ce fichier et le remplir avec des données de votre choix. Utiliser l'exemple de programme C [1] fourni en annexe.
Indications:Utiliser le programme [2] pour accéder au fichier et imprimer la totalité
des enregistrements.
Sur le modèle du programme précédent, écrire maintenant un programme qui
saisit un numéro d'article, cherche cet article dans le fichier et
imprime les informations (nom, prix, quantité) trouvés.
Considérer le cas où l'article de numéro donné n'existe pas et imprimer un message dans ce cas.
Reprendre le programme de la question 1. et créer le fichier cette fois-ci en saisissant les
numéros d'article par ordre croissant.
Refaire la question 3. en optimisant cette fois-ci la recherche.
Dans cet exemple de fichier les enregistrements sont rangées de
façon consécutive et numérotées de 0 jusqu'à n-1,
pour un fichier de taille n.
Exemple: Fichier avec 5 enregistrements (présentés verticalement ici)

En langage C, La taille d'un fichier est exprimée en nombre
d'octets. Ici on a un fichier de taille physique 32x5 = 160 octets. Le
début de l'enregistrement "CD" se trouve à l'octet 64 (32 *2) car il est précédé
de 2 enregistrements.
L'appel à la fonction seek permet de se positionner sur un enregistrement avant sa lecture. Le positionnement se calcule en nombre d'octets depuis le début du fichier. Si les enregistrements sont de taille 32 comme ici, l'appel
fseek (farticle, 64, SEEK_SET);
positionne la lecture dans le fichier farticle sur le début de l'enregistrement n° 2 ("CD").
La constante SEEK_SET
(valant 0) sert à indiquer que le calcul 62 se fait par rapport au début
du fichier.
Ainsi, la séquence d'instructions suivante:
cle = 2; /* on va lire l'enr. n° 2*/
position = cle * sizeof(TYPEART); /* on calcule la position (2x32 = 64) */
fseek(farticle, position, SEEK_SET); /* deplacement dans le fichier vers l'octet position
fread(&article, sizeof(article), 1, farticle); /* lecture de l'enr.*/
lit l'enregistrement qui contient "CD". (On aura article.num = 34, article.nom = "CD" etc.)
Remarque: On a SEEK_CUR
ou SEEK_END, valant
respectivement 1 et 2, qui indiquent le calcul par rapport à la position
courante ou la fin de fichier resp.
Exercice: Ecrire un
programme qui saisit un entier n et qui lit le n-ième
enregistrement dans le fichier pour afficher son nom. Pour n
= 4 on doit afficher Livre.
(Créer au préalable le fichier ci-dessus).
Dans l'exercice précédent, on accède directement à un article étant donné
son rang dans le fichier (si toutefois on le connaît). Or le rang
n'est une caractéristique d'article comme le numéro, le prix ou le nom.
On voudrait surtout accéder à un article étant donné son numéro (ou son nom ou autre caractéristique). Pour chercher son prix "20", on voudrait accéder directement à l'article <5, Montre, 20, 10> en donnant son numéro "5" (on dira aussi une clé). Or comment faire correspondre le numéro d'enregistrement (1 ici) au numéro article "20" ?
Il faudrait donc créer un moyen pour faire correspondre à chaque numéro d'article son rang dans le fichier. On peut le faire de deux façons :
Une idée de réaliser cet accès est de créer un index
donc. C'est un deuxième fichier qui contient pour chaque clé numéro
d'article, le rang physique de l'enregistrement dans le fichier. C'est à
dire au numéro d'article 11 on fait correspondre le rang 3. Voir figure
ci-dessous.

Le fichier index est constitué d'enregistrements ayant deux champs <clé,
rang>. Le fichier index est
trié par rapport au champs clé.
La recherche du l'article 11 par exemple, se fait en deux étapes:
On parcourt séquentiellement le fichier article à indexer, et on sauvegarde dans un tableau les couples <numéro article, i> i=0..n. Soit ici <12, 0>, <5, 1>, <34, 2>, <11, 3>, <8, 4> etc. On trie ce tableau par ordre croissant de numéro article. Soit <5, 1>, <8, 4>, <11, 3> etc. On crée ensuite le fichier index à partir de ce tableau trié.
NB. Dans un premier temps, on ne considérera pas cette méthode, et on
créera l'index "à la main" (en saisissant les valeurs sur le clavier) pour
se concentrer sur la recherche indexée (Etape 1 et 2 ci-dessus).
Exercices:
Voir TP.
#include <stdio.h>
#include <sys/stat.h>
/*#include <conio.h>*/
/* Declarations des types*/
typedef struct {
int numero;
char nom[20];
float prixHT;
int qte;
} TYPEART;
/* Declarations des variables*/
FILE *farticle; /* le fichier des articles */
TYPEART article; /* un article donné*/
void lireArticle();
int main() {
int n;
/* Ouverture ou création du fichier article.date */
farticle = fopen("article.dat", "w");
/* Lecture d'un article. n°= 0 signifie fin */
lireArticle();
/* Boucle d'écriture des article dans le fichier */
while (article.numero) {
/* Ecriture dans fichier */
fwrite(&article, sizeof(article), 1, farticle);
/* Lecture article suivant. n°= 0 si fin */
lireArticle();
}
/* Fin traitement et fermeture du fichier */
fclose(farticle);
}
void lireArticle(){
printf("rentrer numero article (0=fin): ");
scanf("%d", &article.numero);
if (article.numero == 0) return; /* fin */
printf("rentrer nom article: ");
scanf("%s", article.nom);
printf("rentrer prixHT article: ");
scanf("%f", &article.prixHT);
printf("rentrer quantité en stock: ");
scanf("%d", &article.qte);
}
[2] Lecture et impression des
enregistrements
#include <stdio.h>
#include <sys/stat.h>
typedef struct {
int numero;
char nom[20];
float prixHT;
int qte;
} TYPEART;
int main() {
FILE *farticle;
TYPEART article;
int n;
/* Ouverture fichier */
farticle = fopen("article.dat", "r");
/* Lecture d'un premier enregistrement si existe */
n = fread(&article, sizeof(article), 1, farticle);
/* (n ≠ 0) indique qu'un enregistrement a été lu */
/* Boucle de traitement des enregistrements lus */
while (n != 0) {
printf("%d %s %f %d\n", article.numero,
article.nom,
article.prixHT,
article.qte);
/* Lecture enregistrement suivant si existe*/
n = fread(&article, sizeof(article), 1, farticle);
}
/* Fin tratement et fermeture fichier */
fclose(farticle);
}
[3] ... à suivre