Énoncé
Au cours de l'unité IGI-3004 (et de l'atelier PR-3006), plusieurs processus
seront amenés à s'échanger des messages à travers différents types de "fichier"
(fichiers texte, tubes, entrés/sorties standards par exemple). Il est possible
grâce aux appels systèmes read et write
d'écrire et de lire de manière générique ces fichiers quels que soient leurs
types. L'objectif de cet exercice est d'initier l'implémentation en C d'une
bibliothèque de lecture et écriture de fichiers. Cette bibliothèque sera appelé
'gestionFichiers' dans la suite et se composera des fichiers
gestionFichiers.h
et gestionFichiers.c
.
Remarque importante : Utilisez l'appel système
open pour ouvrir un fichier, close pour le
fermer et read et write pour lire et écrire à
l'intérieur. Avant toute manipulation de ces fonctions consultez leur
documentation en tapant 'man 2 open', 'man 2
read', 'man 2 write' et 'man 2
close'.
1. - L'objectif de cette première
question est d'implémenter une première fonction dans la bibliothèque
gestionFichiers (lecture de 10 caractères). Le prototype de cette fonction sera
inclus dans le fichier gestionFichiers.h
(question 1a). Son
implémentation sera donnée dans le fichier gestionFichiers.c
(question 1b). Enfin, le test d'utilisation sera codé dans le fichier
test1c.c
(question 1c).
1a. Écrivez dans le fichier
gestionFichiers.h
le prototype de la fonction spécifiée ci-dessous
:
- nom : litDixCaracteres ;
- paramètre : un descripteur de fichier ;
- valeur de retour : une chaîne de caractères contenant les
dix premiers caractères lus dans le fichier identifié par le descripteur passé
en paramètre.
Rappels.
- Une chaîne de caractères en C est un tableau contenant les caractères de la chaîne suivis du caractère de fin de chaîne '\0'. Vous veillerez donc à ce que la chaîne de caractères retournée par votre fonction soit bien formatée, c'est-à-dire qu'elle se termine par le caractère de fin de chaîne '\0'. Par exemple la chaine de caractère "ExempleDix" est représentée par le tableau :
indice | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
chaîne : | 'E' | 'x' | 'e' | 'm' | 'p' | 'l' | 'e' | 'D' | 'i' | 'x' | '\0' |
- Un tableau en C est référencé par
l'adresse de son premier élément, c'est-à-dire par un pointeur vers son premier
élément. Par exemple, le type d'un tableau d'entiers est donc int *.
- Un descripteur de fichier est un petit entier positif
utilisé par le système d'exploitation pour identifier un fichier préalablement
ouvert par le programme en cours d'exécution. Les appels systèmes de
manipulation des fichiers utilisent ce descripteur pour identifier les fichiers
à traiter.
1b. Écrivez dans le fichier
gestionFichiers.c
la fonction correspondant au prototype décrit à
la question 1a.
Rappels.
- L'appel système read sera utilisé
pour lire dans un fichier. Consultez sa documentation en tapant 'man 2
read' dans un terminal.
- La fonction malloc permet d'allouer de la mémoire. Elle
retourne l'adresse du bloc mémoire alloué. Par exemple, l'appel 'malloc(10 *
sizeof(int))' alloue un bloc mémoire permettant de sauvegarder 10 entiers et
retourne l'adresse de début de ce bloc mémoire. Consultez la documentation de
malloc : 'man malloc' dans un terminal.
1c. Implémentez, dans le fichier
test1c.c
, la fonction main permettant de tester l'unique fonction
de votre bibliothèque (c'est-à-dire la fonction litDixCaracteres). Pour cela,
votre programme devra ouvrir le fichier donné ici, lire ses dix premiers caractères à l'aide de
litDixCaracteres et les afficher à l'écran.
Rappel. L'appel système open sera utilisé pour ouvrir un fichier. Consultez sa documentation en tapant 'man 2 open' dans un terminal.
1d. Afin d'automatiser la compilation, écrivez le fichier makefile permettant de compiler votre bibliothèque et sa fonction de test lorsque l'on tape 'make' au terminal.
Rappel. Les rappels sur makefile et la compilation séparée sont disponibles ici.
2. - L'objectif est de cette question est d'intégrer une seconde fonction dans la bibliothèque gestionFichiers. Celle ci sera un peu plus utile pour le suite de l'unité que celle implémentée en question 1.
2a. Intégrez à la bibliothèque gestionFichiers la fonction spécifiée ci-dessous :
- nom : litLigne ;
- paramètre : un descripteur de fichier ;
- valeur de retour : une chaîne de caractères correspondant à
la premère ligne lue depuis le descripteur de fichier passé en paramètre,
si celle-ci a une taille inférieure à une constante TAILLEBUF (que
vous définirez dans labibliothèque) ou le pointeur NULL, sinon pour
indiquer un erreur.
2b. - Dans cinq autres fichiers C distincts vous implémenterez cinq fonctions main permettant de tester votre bibliothèque.
- test2b1.c
: un programme qui ouvre le
fichier donné ici et affiche sa première ligne
à l'écran.
- test2b2.c
: un programme qui ouvre et affiche la première ligne
du fichier passé comme argument au lancement de l'exécution du programme. Par
exemple, lorsque l'on tape ./test2b2 fichier.txt
dans un terminal,
le fichier nommé fichier.txt
devra être lu.
Rappel. Pour récupérer les
arguments d'un programme en C vous devez utiliser les arguments int
argc
et char **argv
passé à la fonction main
(voir par exemple main).
- test2b3.c
: un programme qui affiche
toutes les lignes du fichier passé en argument.
- test2b4.c
: un programme qui affiche le nombre de lignes du
fichier passé en argument. Pour compter le nombre de ligne vous devez utiliser
la fonction de votre bibliothèque
- test2b5.c
: que se passe-t-il si vous passez la valeur 0 en
paramètre de votre fonction de lecture d'une ligne ? Implémentez, dans le
fichier test2b5.c
, un programme permettant de répondre à cette
question.
3a. - Ajouter à la bibliothèque gestionFichiers une procédure permettant d'écrire une chaîne de caractère dans un fichier. Cette procédure prendra donc comme paramètre un descripteur de fichier et une chaîne de caractères.
3b. Dans trois autres fichiers C distincts vous implémenterez trois fonctions main pour tester cette nouvelle fonction de votre bibliothèque.
- test3b1.c
: un programme qui accepte
en arguments le nom de deux fichiers et copie le contenu du premier fichier
dans le second.
- test3b2.c
: que se passe-t-il si vous passez la valeur 1 en
paramètre de votre fonction d'écriture ? Implémentez, dans le fichier
test3b2.c
, un programme permettant de répondre à cette question.
- test3b3.c
: un programme qui recopie dans le terminal (c'est à
dire sur la sortie standard) chaque ligne tapée au clavier (c'est à dire entrée
sur l'entrée standard) en utilisant les fonctions de votre bibliothèque. Que
doit-on taper au clavier pour terminer votre programme ?
Ce sujet a été élaboré par Jean COUSTY et
Laurent NAJMAN
Laboratoire d'Informatique Gaspard-Monge, Université Paris-Est - Département
Informatique, ESIEE Paris