Un exemple d`utilisation des fichiers texte en Ada.

Transcription

Un exemple d`utilisation des fichiers texte en Ada.
Un exemple d'utilisation des fichiers texte en Ada.
Le programme suivant a pour objet de lire des tableaux 2D de caractères dont le contenu a été mémorisé dans des fichiers
texte (lisibles et modifiables avec un éditeur de texte tel que Notepad, Gedit, Emacs …).
Le type de ces tableaux est non contraint pour que le programme puisse manipuler des tableaux de taille quelconque.
Chaque fichier peut donc contenir un tableau différent (en nombre de lignes et de colonnes).
Le problème qui est posé est celui de la déclaration de variables tableaux dont les dimensions dépendent du traitement d'un
fichier texte : en effet il faut :
ouvrir le fichier pour y lire les dimensions du tableau,
déclarer la variable tableau
affecter à cette variable les valeurs contenues dans le reste du fichier texte.
On a donc convenu que les fichiers contenant des tableaux 2D auraient une structure particulière. Un fichier doit contenir une
première ligne avec deux entiers N et M : N est le nombre de lignes du tableau, M son nombre de colonnes ; ensuite, les
lignes suivantes du fichier (de la 2ème à la dernière) contiennent le tableau lui-même à raison d'une ligne de fichier par ligne du
tableau, ex : le fichier lab1.txt ci-dessous. Ces conventions facilitent la lecture.
La solution consiste à lire tout d'abord les dimensions du
tableau N et M, puis utiliser un bloc Declare…Begin…End;
pour déclarer et dimensionner le tableau ; le corps de ce
bloc consiste à lire des caractères à l'aide d'une double
boucle for (une boucle for externe pour les lignes, une
boucle for interne pour les colonnes) ; le nombre
d'itérations des boucles est contrôlé par N et M qui ont été
lus précédemment.
Pour illustrer l'utilisation de tableaux 2D et leur sauvegarde
sur des fichiers texte, on a repris l'exemple des tableaux de
caractères représentant des labyrinthes (voir TD3).
with Ada.Text_Io, Ada.Integer_Text_Io;
use Ada.Text_Io, Ada.Integer_Text_Io;
procedure Test_Lecture_Fichiers is
--*************
-- declarations
--*************
--********************
-- types et sous-types
--********************
type Un_Labyrinthe is array(Natural range <>, Natural range <>) of Character;
--************************
-- specs des ss-programmes
--************************
procedure Lire_Labyrinthe(F : in File_Type; Le_Labyrinthe : out Un_Labyrinthe);
procedure Afficher_Labyrinthe(Le_Labyrinthe : in Un_Labyrinthe);
procedure Test_Chargement_Labyrinthe_Depuis_Fichier;
--************************
-- corps des ss-programmes
--************************
procedure Lire_Labyrinthe(F : in File_Type; Le_Labyrinthe : out Un_Labyrinthe) is --lecture d'un tableau 2D dans un fichier deja ouvert
begin
for Line in Le_Labyrinthe'range(1) loop
for Colum in Le_Labyrinthe'range(2) loop
Get(F, Le_Labyrinthe(Line, Colum)); -- lecture d'un caractere dans le fichier et remplissage d'une case du tableau
end loop;
Skip_Line(F);
-- une ligne entiere a ete lue. On se positionne sur la ligne suivante.
end loop;
end Lire_Labyrinthe;
procedure Afficher_Labyrinthe(Le_Labyrinthe : in Un_Labyrinthe) is
begin
New_line;
for Line in Le_Labyrinthe'range(1) loop
for Colum in Le_Labyrinthe'range(2) loop
Put(Le_Labyrinthe(Line, Colum));
end loop;
New_Line;
end loop;
end Afficher_Labyrinthe;
-- affichage ecran classique d'un tableau 2D
procedure Test_Chargement_Labyrinthe_Depuis_Fichier is
FileName : String(1..300);
-- nom physique du fichier (300 caracteres = longueur maximale toleree)
NameLong : Natural;
-- longueur reelle du nom (nombre de caracteres saisis avant l'appui sur la touche <Retour>)
F : Ada.Text_Io.File_Type; -- nom symbolique du fichier
Nb_Lignes, Nb_Colonnes : Natural; -- dimensions du labyrinthe (c'est un tableau 2D)
Fini
: Boolean;
-- vrai des que l'utilisateur veut quitter ou des que le programme rencontre un probleme de fichier
begin
loop
-- debut de la boucle Repeter … Jusqu'à
New_Line;
Put("Nom du fichier labyrinthe ? ");
Get_Line(FileName, NameLong);
-- Get_Line retourne le nom du fichier et le nombre de caracteres sigificatifs
if NameLong = FileName'Length then -- Dans le cas tres rare ou l'utilisateur saisirait un nom de 300 caracteres ...
Skip_Line;
-- il faut effacer le caractere <Retour> qui suit la saisie sinon
end if;
-- cela peut perturber les saisies suivantes (saisies de Nb_Colonnes et Nb_Lignes)
if NameLong = 0 then --L'utilisateur signale qu'il veut quitter le programme en appuyant directement sur <Retour>
Fini := True;
-- (=> le nom du fichier est donc de longueur=0 ; aucun des 300 caracteres n'a ete affecte)
else
Fini := False;
begin
Open(F, In_File, FileName(1..NameLong)); -- On essaie d'ouvrir le fichier (erreur possible sur le nom : cas 1)
Get(F, Nb_Lignes);
-- Le fichier existe : on lit le nb de lignes (erreur possible sur le contenu : cas 2)
Get(F, Nb_Colonnes); -- puis on lit le nb de colonnes du labyrinthe (erreur possible sur le contenu : cas 2)
Skip_Line(F);
-- Si tout est ok, on se positionne sur la ligne suivante dans le fichier
declare
-- Creation d'un tableau labyrinthe aux dimensions lues dans le fichier
Le_Labyrinthe : Un_Labyrinthe(1..Nb_Lignes, 1..Nb_Colonnes);
begin
-- Remplissage du tableau qui vient d'etre cree
Lire_Labyrinthe(F, Le_Labyrinthe); -- on passe la main au ss-programme (erreur possible sur le contenu du fichier)
Close(F);
-- Si tout s'est bien passe, on peut refermer le fichier qui avait ete ouvert
New_Line;
Afficher_Labyrinthe(Le_Labyrinthe); -- On affiche le labyrinthe (pour verification du ss-prog de lecture)
end;
exception -- Traitement des exceptions liées aux fichiers (attention le fichier est peut-être encore ouvert)
when Ada.Text_Io.Name_Error => --cas 1 ou le nom de fichier est incorrect (il n'a pas pu etre ouvert)
Put_Line ("Aucun fichier de ce nom ! Fin du programme. Ciao ... ");
Fini := true;
when Ada.Text_Io.Data_Error => --cas 2 ou le contenu du fichier est incorrect (ce fichier est encore ouvert ..)
Close(F);
-- il faut penser a le refermer
Put_Line("Le fichier existe mais son contenu est incorrect ! Fin du programme. Ciao ... ");
Fini := true;
end;
end if;
exit when Fini;
-- sortie de la boucle Repeter … Jusqu'à …
(Fini=True)
end loop;
end Test_Chargement_Labyrinthe_Depuis_Fichier;
--****************************
--corps du programme principal
--****************************
begin
Test_Chargement_Labyrinthe_Depuis_Fichier;
end Test_Lecture_Fichiers;
Exemples de fichiers :
Fichier bien construit
(5 lignes 7 colonnes)
Fichier bien construit
(15 lignes 26 colonnes)
Fichier mal construit (la lecture va planter car
il n'y a pas 15 lignes de 35 caracteres)
Exemples d'exécution :
Tests sur 3 fichiers existants dont l'un est mal construit
Test sur un fichier inexistant

Documents pareils