Exercices sur les  fichiers et les méthodes d'accès

(en langage C)

1ère année Informatique.
Najib Tounsi

Sommaire

  1. 1. Création de fichier
  2. 2. Consultation en accès séquentiel
  3. 3. Recherche d'un enregistrement de numéro donné (en accès séquentiel)
  4. 4. Recherche d'un enregistrement de numéro donné (bis). Fichier trié par numéro article
  5. 5. Accès direct à un enregistrement du fichier
    1. 5.1 Accès direct par n° enregistrement
    2. 5.2 Accès direct par n° article
      1. Accès par Index.
      2. Création du fichier index.
      3. Accès par H-Code
  6. Annexe


1. Création de fichier

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:

2. Consultation en accès séquentiel

Utiliser le programme [2] pour accéder au fichier et imprimer la totalité des enregistrements.

3. Recherche d'un enregistrement de numéro donné (en accès séquentiel)

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.

4. Recherche d'un enregistrement de numéro donné (bis). Fichier trié par numéro article

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.

5. Accès direct à un enregistrement du fichier

5.1 Accès direct par n° enregistrement

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)

Fichier articles

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).

5.2 Accès direct par n° article

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 :

Accès par Index.

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.

image fichier indexé

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:

Création du fichier index.

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:

  1. Ecrire un programme C qui crée les deux fichiers, index et indexé, ci-dessus. Utiliser le programme de la question 1 pour cela. On s'appliquera à rentrer des valeurs justes pour l'index!
  2. Ecrire un programme  qui fait la recherche du nom d'un article étant donné son numéro. Le programme doit utiliser l'index ainsi créé.
  3. Faire de même avec un index sur les noms cette fois-ci. Ecrire le programme qui cherche le prix d'un article de nom donné.
    Dans ce dernier cas, peut-on considérer des noms double? (Rep: oui. Si par exemple il y a deux ou trois nom "Montre", dans le fichier index, il y aura 2 ou 3 d'enregistrements qui se suivent et qui pointent chacun sur l'article correspondant).

Accès par H-Code

Voir TP.

Annexe

[1] Création de fichier (en C standard)
#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