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

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

Date de publication : 21/11/2009


V. Traitement d'un fichier de type CSV
V-1. Fonction : get_contact
V-2. Code source complet


V. Traitement d'un fichier de type CSV

Un fichier CSV (Comma-separated values), est un fichier représentant des données tabulaires. Chaque valeur est délimitée par une virgule ou point-virgule (suivant la localisation ou le programme qui génère le fichier). Si vous ne connaissez pas ou pas trop ce type de fichier, vous pouvez en savoir plus en suivant ce fr lien. Ici nous allons voir la forme la plus simple de ce type mais il en existe plusieurs formes, voici notre exemple :
Robert;Dupont;12 rue du verger;Strasbourg;67000
info Le code étant assez simple à mettre en oeuvre, nous n'allons pas passer par une étude algorithmique mais nous allons nous plonger directement dans le vif du sujet !

V-1. Fonction : get_contact

contact_infos * get_contact (const char * filename)
{
   contact_infos  *  infos = NULL;
   FILE           *  file  = NULL;
   char           *  token = NULL;
   char              buff [BUFF_SIZE];


   file = fopen (filename, "r");                            /* 1.- */

   if (file != NULL)
   {
      if ((fgets (buff, BUFF_SIZE, file)) != NULL)          /* 2.- */
      {
         char *   p = buff;
         int      i = 0;


         infos = malloc (sizeof (* infos));                 /* 3.- */

         if (infos != NULL)
         {
            while ((token = strtok (p, DELIM)) != NULL)     /* 4.- */
            {
               if (i == 0)
                  p = NULL;                                 /* 5.- */

               switch (i)                                   /* 6.- */
               {
                  case NOM:
                     infos->nom = str_dup (token);
                     break;

                  case PRENOM:
                     infos->prenom = str_dup (token);
                     break;

                  case ADRESSE:
                     infos->adresse = str_dup (token);
                     break;

                  case VILLE:
                     infos->ville = str_dup (token);
                     break;

                  case CODE:
                  {
                     int code = strtol (token, NULL, 10);
                     infos->code = code;
                  }
                  break;

                  default:
                     break;
               }

               i++;
            }
         }
      }

      fclose (file);
   }


   return infos;
}
info Dans notre exemple, cette fonction ne lit que la première ligne du fichier passé en argument mais avec quelques modifications, il est tout à fait possible de lui faire rechercher un contact précis !
La fonction retourne une structure dans le même genre que celle que nous avons utilisé dans le Chapitre III :
typedef struct
{
   char *   nom;
   char *   prenom;
   char *   adresse;
   char *   ville;
   int      code;
}
contact_infos;
Les constantes utilisées dans l'instruction switch sont définies ainsi :
typedef enum
{
   NOM,		/* commence a l'index O par defaut */
   PRENOM,
   ADRESSE,
   VILLE,
   CODE,

   NB_TYPE
}
infos_type;
Voyons le déroulement de la fonction :

On commence comme d'habitude par ouvrir notre fichier (1), ici celui dont le nom a été passé en argument. On lit la première ligne du fichier (2), si la ligne a été lue avec succès, on alloue un espace pour notre structure (3). Après le teste d'allocation, nous utilisons la fonction strtok pour extraire les informations (4), parlons-en un peu de cette fonction...

strtok permet d'extraire des mots d'une chaîne (éléments léxicaux) en lui fournissant une suite de délimiteurs. Il faut cependant être très prudent avec cette fonction car elle modifie la chaîne passée en argument. Après chaque mot trouvé, elle met un caractère '\0' après le délimiteur, si vous devez donc réutiliser la chaîne plus tard, il est conseillé de travailler sur une copie de la chaîne ! Vous pouvez voir dans le code ci-dessus (5) que nous mettons le pointeur p, qui pointe sur la chaîne, à la valeur NULL. Ceci pour la simple et bonne raison que cet argument doit être à cette valeur (c'est pour cette raison également que nous utilisons ce pointeur car on ne peut mettre un tableau statique à NULL) pour les appels suivants sinon, la fonction recommence au début de la chaîne.

On termine ensuite par une simple instruction switch pour récupérer les informations une à une (6), à chaque mot (token ou élément léxical) trouvé correspond donc une information.


V-2. Code source complet

Fichier : contacts.csv
Robert;Dupont;12 rue du verger;Strasbourg;67000
Fichier : main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define DELIM        ";"
#define BUFF_SIZE    128


typedef struct
{
   char *   nom;
   char *   prenom;
   char *   adresse;
   char *   ville;
   int      code;
}
contact_infos;


typedef enum
{
   NOM,
   PRENOM,
   ADRESSE,
   VILLE,
   CODE,

   NB_TYPE
}
infos_type;


static char * str_dup (const char * str)
{
   char * dup = NULL;


   if (str != NULL)
   {
      size_t size = strlen (str) + 1;
      dup = malloc (size);

      if (dup != NULL)
      {
         memcpy (dup, str, size);
      }
   }


   return dup;
}


static contact_infos * get_contact (const char * filename)
{
   contact_infos  *  infos = NULL;
   FILE           *  file  = NULL;
   char           *  token = NULL;
   char              buff [BUFF_SIZE];


   file = fopen (filename, "r");

   if (file != NULL)
   {
      if ((fgets (buff, BUFF_SIZE, file)) != NULL)
      {
         char *   p = buff;
         int      i = 0;


         infos = malloc (sizeof (* infos));

         if (infos != NULL)
         {
            while ((token = strtok (p, DELIM)) != NULL)
            {
               if (i == 0)
                  p = NULL;

               switch (i)
               {
                  case NOM:
                     infos->nom = str_dup (token);
                     break;

                  case PRENOM:
                     infos->prenom = str_dup (token);
                     break;

                  case ADRESSE:
                     infos->adresse = str_dup (token);
                     break;

                  case VILLE:
                     infos->ville = str_dup (token);
                     break;

                  case CODE:
                  {
                     int code = strtol (token, NULL, 10);
                     infos->code = code;
                  }
                  break;

                  default:
                     break;
               }

               i++;
            }
         }
      }

      fclose (file);
   }


   return infos;
}


static void free_contact_infos (contact_infos ** p)
{
   if (p != NULL && *p != NULL)
   {
      free ((*p)->nom);
      free ((*p)->prenom);
      free ((*p)->adresse);
      free ((*p)->ville);

      free (*p);
      *p = NULL;
   }
}



int main (void)
{
   contact_infos * infos = get_contact ("contacts.csv");

   if (infos != NULL)
   {
      printf (
         "Nom complet : %s %s\nAdresse : %s\nVille : %d %s\n\n",
         infos->nom, infos->prenom, infos->adresse, infos->code, infos->ville
      );

      free_contact_infos (& infos);
   }


   return EXIT_SUCCESS;
}
Sortie sur la console
Nom complet : Robert Dupont
Adresse : 12 rue du verger
Ville : 67000 Strasbourg
 

Valid XHTML 1.0 TransitionalValid CSS!

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.