IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Extraction d'informations depuis un fichier de données en C


précédentsommairesuivant

III. Traitement d'un fichier avec une structure personnalisée

Dans ce premier chapitre, nous allons voir comment récupérer des informations dans un fichier avec une structure de données personnalisée soit, la structure suivante :

 
Sélectionnez
{
   name:Franck.H
   age:32
   address:16 rue du General de Gaulle, 67000 Strasbourg
   phone:0618325015
}

Dans ce type de structure, les accolades délimitent un bloc de données, ce qui nous permet donc de déterminer à quel moment dans le code, il faut commencer à tester et récupérer les informations. Le caractère ':' sert de séparateur entre une donnée et son nom de champ dans le fichier, on pourrait aussi mettre par exemple le caractère '=' qui est plus souvent utilisé dans ce cas de figure.

III-1. Étude algorithmique

Il faut pour commencer, déterminer un algorithme et donc un cheminement permettant de partir de l'ouverture d'un bloc de données jusqu'à dans notre cas, la recherche du nom d'un contact puis de récupérer ses données personnelles. Cela vaut pour tout autre programme. Voici un algorithme possible :

 
Sélectionnez
Ouvrir fichier
   Tant que ligne <> NIL lire ligne fichier
      Si caractère 0 de ligne égal à '{'
         alors ouvrir bloc
         sinon si bloc ouvert
            Si recherche label égal à "name"
               alors
                  Récupérer l'âge
                  Récupérer l'adresse
                  Récupérer le téléphone
            Fsi
      Fsi
   Fin tant que
Fermer fichier

Voici une brève explication du cheminement.

  1. On ouvre le fichier à lire.
  2. On lit le fichier ligne par ligne par le biais d'une boucle Tant que(while) tant qu'on ne se trouve pas à la fin du fichier.
  3. On teste sur chaque ligne et tant qu'un bloc n'a pas été ouvert, si le premier caractère de la chaîne est un caractère '{'
  4. Si un bloc n'a pas encore été ouvert et que le premier caractère est '{', on ouvre le bloc en initialisant une variable d'état (généralement de type booléen, mais un type entier convient très bien aussi). On saute ensuite à la prochaine ligne.
  5. Si un bloc a déjà été ouvert, on recherche le nom du contact à retrouver en commençant par rechercher l'enregistrement portant l'identifiant « name ». Si cet identifiant a été trouvé, on compare le nom qui le suit avec le nom à retrouver.
  6. Si le contact a été retrouvé, on récupère une à une ses informations.
  7. Fermeture du fichier.

III-2. Implémentation

Attelons-nous maintenant à l'écriture du code en C. Il nous faut pour commencer, inclure les fichiers d'en-tête adéquats :

 
Sélectionnez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Nous devons maintenant préparer diverses parties pour pouvoir développer notre futur code. Nous allons plutôt utiliser des directives du préprocesseur pour définir quelques constantes symboliques ce qui permettra une plus grande facilité dans la maintenance future du code (il faut toujours penser à la maintenance du code) et aussi, rendra le code plus lisible.

 
Sélectionnez
#define BEGIN        '{'
#define SEP          ':'
#define BUF_SIZE     128
#define FILENAME     "perso.txt"

#define TAG_NAME     "name"
#define TAG_AGE      "age"
#define TAG_ADRESS   "address"
#define TAG_PHONE    "phone"

Les constantes commençant par « TAG_ » sont en fait les différents champs qu'on retrouve dans un bloc de données du fichier. La constante BUF_SIZE permet de définir la limite d'un tableau de caractères donc le nombre maximum de caractères que peut contenir une chaîne après la lecture.

III-2-1. Fonction : get_infos

 
Sélectionnez
contact_infos * get_info (const char * contact_name);

Voici la fonction principale qui va faire presque tout le travail, elle retourne une structure de type contact_infos dont voici la définition :

 
Sélectionnez
typedef struct
{
   char *   name;
   char *   adress;
   char *   phone;
   int      age;
}
contact_infos;

Et prend comme unique paramètre le nom du contact à retrouver. Voici l'implémentation de la fonction :

 
Cacher/Afficher le codeSélectionnez

On peut revoir grâce à la numérotation en commentaire, les principales actions de l'explication du cheminement du chapitre sur l'étude algorithmique. J'ai parlé durant cette étude d'un entier qui peut servir de drapeau booléen pour déterminer l'ouverture d'un bloc de données, c'est ce que fait la variable opened. On peut voir dans la partie 5 du code, la recherche du tag name. Juste après, dans la condition if, on décale le pointeur sur la longueur du tag plus 1 caractère pour passer après le séparateur de champs ':' donc au début du nom du contact.

S'en suit la comparaison entre le nom du contact retrouvé et celui passé en argument à la fonction. Si c'est la bonne personne, on alloue dynamiquement un espace pour la structure que doit renvoyer la fonction et on la remplit par le biais d'une seconde fonction nommée get que nous allons voir juste après.

On peut apercevoir l'utilisation de constantes en troisième argument de cette seconde fonction, voici l'énumération correspondante qui servira à récupérer la suite des informations du contact :

 
Sélectionnez
typedef enum
{
   NAME,
   AGE,
   ADDRESS,
   PHONE,

   NB_TAG
}
contact_tags;

III-2-2. Fonction : get

 
Sélectionnez
void get (contact_infos * p, FILE * file, contact_tags tag);

Cette fonction permet de terminer la récupération des informations restantes d'un contact. Ses trois arguments sont dans l'ordre :

  • un pointeur valide sur la structure que doit renvoyer la fonction get_infos ;
  • un pointeur valide sur le fichier en cours de lecture ;
  • le tag de type contact_tags correspondant à l'information que doit récupérer la fonction.

Voici l'implémentation de la fonction :

 
Cacher/Afficher le codeSélectionnez

À chaque appel de la fonction, on lit la ligne suivante (1) du fichier. À partir de la ligne récupérée, on recherche (2) la position du séparateur de champs. Si le séparateur a été trouvé, on décale le pointeur de 1 caractère (3) pour se retrouver au début de la donnée à récupérer. On finalise enfin la chaîne (4) afin d'y ajouter un caractère de fin de chaîne en lieu et place du saut de ligne. Nous pouvons maintenant récupérer la donnée courante (5) suivant le tag passé en argument.

Vous pouvez remarquer la conversion de l'âge en entier lors de la récupération de cette donnée. Ici l'ordre de récupération des données est immuable, mais il est tout à fait possible de créer une fonction plus souple, mais qui demande davantage de temps et de lignes de code.

III-3. Code source complet

Voici le code source complet avec en plus le contenu du fichier perso.txt et la sortie sur la console. Dans le code vous pourrez apercevoir les fonctions décrites jusque là et une fonction contact_infos_free qui permet de libérer la mémoire allouée dynamiquement pour la structure contact_infos.

Fichier : perso.txt
Cacher/Afficher le codeSélectionnez
Fichier : main.c
Cacher/Afficher le codeSélectionnez
Sortie sur la console
Sélectionnez
Franck.H
32
16 rue du General de Gaulle, 67000 Strasbourg
0618325015

précédentsommairesuivant

Copyright © 2009 Franck Hecht. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.