IV. Traitement d'un fichier de type INI▲
Dans ce chapitre nous allons étudier un format plus commun, un fichier de type *.ini comme ceux qu'on trouve sur le système Windows ou encore dans le même esprit, les fichier *.conf qu'on peut trouver sur les Unixoïdes. Ce type de fichier est le plus souvent utilisé pour stocker les préférences utilisateurs d'un programme. Voici l'exemple sur lequel nous allons travailler :
[user]
alias=Franck.H
name=HECHT Franck
[server]
server=192.160.1.10
port=147
[files]
backup=backup.dat
log=log.dat
error=error.dat
IV-1. Étude algorithmique▲
Comme le chapitre précédent et tout code digne de ce nom, il faut établir un algorithme au moins minimaliste avec les étapes principales qui serviront de fil rouge au code qu'on produira par la suite :
Ouvrir fichier
Tant que ligne <> NIL lire ligne fichier
Si section non ouverte et caractère 0 de ligne égal à '['
Test de la chaîne entre crochets
Si section égal OK
Ouvrir section
Fsi
Sinon si section ouverte
Si caractère 0 de ligne égal à '['
Fermeture section
Sortie de la boucle
Fsi
Recherche de la clé
Si clé trouvée
Récupération donnée
Sortie de la boucle
Fsi
Fsi
Fin tant que
Fermer fichier
Le principe reste assez simple ! Nous lisons le fichier ligne par ligne, il faut tester le premier caractère de la ligne courante si la section n'a pas encore été ouverte/trouvée, ceci permet de détecter une section. Si la section a été trouvée et ouverte, on commence par tester la même condition qu'au départ dans le cas où on se trouverait en dehors de la section où il faut chercher les informations. Nous recherchons ensuite simplement la clé puis on en extrait la donnée.
IV-2. Implémentation▲
Nous allons découper le code en plusieurs fonctions comme dans le chapitre précédent, une fonction nommée get qui servira à lire un enregistrement et qui ne sera pas visible directement par l'utilisateur et pour notre exemple, une fonction get_string (qui va récupérer une chaîne) et get_integer (qui servira à récupérer une valeur entière).
Voici le nécessaire pour commencer (ajoutez également les deux fonctions fournies dans les prérequis) :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME "conf.ini"
#define BUF_SIZE 128
#define BEGIN '['
#define SEP '='
Ceci est le début du code, soit les fichiers d'en-tête ainsi que quelques constantes symboliques nécessaires à la suite du code. On précise ici tout de suite le nom du fichier par la constante FILENAME, on ajoute à cela la constante BEGIN qui symbolise le début d'une section et le séparateur par la constante SEP.
IV-2-1. Fonction : get▲
Cette fonction prend trois arguments
- Le nom du fichier INI ;
- Le nom de la section ;
- Le nom de la clé d'enregistrement.
Comme d'habitude, on ouvre le fichier passé en argument (1), on lit le fichier ligne par ligne avec une boucle while et avec la fonction fgets. Avant toute autre opération sur la chaîne récupérée, on remplace le saut de ligne qui est automatiquement lu et ajouté par la fonction fgets, par un caractère de fin de chaîne. On teste si la section n'est pas déjà ouverte et en même temps, si le premier caractère est '['(3). Si la condition est vraie, on compare la chaîne (en l'occurrence le nom de la section courante) avec celle passée en argument (4). Si c'est la bonne section, on l'ouvre puis on boucle directement sur la ligne suivante, sinon on continue à chercher la bonne section.
Dans le second cas où la section est déjà ouverte, on commence par tester si le premier caractère de la chaîne n'est pas un début de section. Si tel est le cas, nous avons dépassé la section ouverte sans trouver la clé passée en argument, on quitte alors la boucle et la fonction renvoie NULL. On recherche ensuite avec la fonction strstr(6) la clé dans la chaîne courante, si la clé est trouvée, on recherche la position du séparateur (7) avec la fonction strchr. Si le séparateur est trouvé, on déplace la position du pointeur de 1 caractère pour se trouver sur le premier caractère de la valeur à récupérer puis on copie la chaîne (8) dont le pointeur sera retourné par la fonction.
IV-2-2. Fonction : get_string▲
char
*
get_string (
const
char
*
section, const
char
*
key)
{
return
get (
FILENAME, section, key);
}
Rien de bien compliqué dans cette fonction, elle renvoie simplement la chaîne retournée par la fonction get.
IV-2-3. Fonction : get_integer▲
int
get_integer (
const
char
*
section, const
char
*
key)
{
int
ret =
0
;
char
*
s =
NULL
;
s =
get (
FILENAME, section, key); /* 1.- */
if
(
s !=
NULL
)
{
ret =
(
int
) strtol (
s, NULL
, 10
); /* 2.- */
free (
s); /* 3.- */
}
return
ret;
}
La fonction get_integer permet de renvoyer une valeur entière, ceci est possible grâce à la conversion de la chaîne renvoyée (1) par get. Si le pointeur retourné est différent de NULL, on tente une conversion avec la fonction strtol(2) puis on libère la chaîne (3) qui je le rappelle, est copiée par allocation dynamique.
IV-3. Code source complet▲
Franck.H
192.160.1.10
147