Baniere Saphir Control
http://www.saphir-control.fr/

bar


BACK

Tous ces articles en ligne sur Scilab ont été écrits pour LINUX MAGAZINE FRANCE par les développeurs du Scilab Group. Les articles sont sous licence FDL (Free Documentation Licence)

Scilab : Programmer les entrées sorties



1   Introduction

La plupart des programmes ont besoin d'acquérir, de stocker et de visualiser des données. Dans le cas des programmes de calcul numérique, il s'agit essentiellement de pouvoir lire et écrire des nombres entiers ou flottants et des chaînes de caractères. Ces nombres peuvent être représentés directement par leur codage interne en séquence de bits, on parlera alors d'entrée-sortie binaire ou alors comme du texte ASCII. Dans ce dernier cas la représentation interne est convertie sous une forme lisible par l'utilisateur, on parlera alors d'entrée-sortie formatée. Notons que pour les chaînes de caractères, il n'y a pas de différence entre ces deux types de représentations. Les entrées-sorties formatées présentent l'avantage d'être facilement lues ou écrites par l'utilisateur. Bien évidemment le formatage induit un surcoût de calcul. Les entrées-sorties binaires permettent également de donner la représentation des nombres sans erreur d'arrondi par rapport à leur représentation interne.

2   Dialogue avec l'utilisateur

Scilab offre plusieurs modes de dialogue avec l'utilisateur. Cela peut se faire par l'intermédiaire de l'interface graphique présentée dans un précédent article ou directement sous forme textuelle dans la fenêtre d'entrée-sortie de Scilab.

2.1   Affichage textuel avancé

Au delà de la visualisation par défaut des variables, l'utilisateur peut souhaiter afficher des résultats avec un format particulier. Il est alors possible d'utiliser la fonction mprintf qui émule la procédure printf du langage C. mprintf.dia On notera ici l'usage des formats << C >> %i pour afficher des entiers et %f pour afficher des nombres flottants ainsi que qui dénote le retour à la ligne. Une solution alternative peut être d'utiliser les fonctions et opérations de manipulation de chaînes de caractères . string.dia Dans ce cas c'est la fonction string qui se charge du formatage des nombres, en utilisant la même procédure que celle utilisée pour l'affichage par défaut.
La fonction mprintf permet aussi de visualiser des tableaux de nombres et de chaînes : mprintf2.dia La fonction mprintf réitère le format pour chaque ligne des tableaux de données. Il montre aussi l'usage du format qui produit une tabulation ainsi que des formats %s qui permet le formattage d'une chaîne de caractères et %d qui permet le formattage des entiers.

2.2   Lecture de données à l'écran

Dans certains cas, un programme en cours d'exécution peut avoir à demander à l'utilisateur de fournir des données supplémentaires. La fonction input envoie un message à l'utilisateur et se met en attente d'une réponse qui peut être un simple nombre, une séquence de nombres ou d'une chaîne de caractères selon l'option spécifiée. Le programme ci-dessous demande à l'utilisateur de fournir les caractéristiques d'un article pour créer une base de données de produits: scilab/io1.sce
name=input("Donnez le nom de l"'article","string");
while %t 
  data=input("Donnez son prix, son poids et le nombre en stock");
  if size(data,"*")==3 then break,end
  mprintf("Saisie incorrecte !\n");
end
mprintf("\n%s prix=%.2fF, poids=%.2fkg, stock=%d\n",name,data)
Ici le premier appel à la fonction input avec l'option "string" attend la saisie d'une chaîne de caractères et le suivant, dans la boucle infinie while %t, attendent un vecteur de nombres. Le dialogue utilisateur sera alors :
Donnez le nom de l'article-->Chaise
Donnez son prix, son poids et le nombre en stock-->850.99 5.3 1000

Chaise, prix=850.99F, poids=5.30kg, stock=1000
On notera dans cet exemple l'usage du format %.nf qui précise le format %f en fixant le nombre n de décimales affichées.
Le code précédent peut aussi être écrit en utilisant la fonction mscanf, émulation de la fonction C scanf qui est plus souple que la fonction input : scilab/io2.sce
Donnez le nom de l'article-->Chaise
Donnez son prix, son poids et le nombre en stock-->850.99 5.3 1000

Chaise, prix=850.99F, poids=5.30kg, stock=1000

3   Lecture et écriture des fichiers

Pour accéder à des quantité importantes de données il est en général nécessaire de les stocker dans des fichiers. L'utilisation de fichiers pour les entrées-sorties est plus compliquée que les entrées-sorties à l'écran.

3.1   Chemins des fichiers

Dans Scilab les fichiers sont désignés par leur chemin, de la même façon que pour le système hôte. Ces chemins sont en général donnés par des chaînes de caractères. Ces chemins peuvent être absolus ou relatifs au répertoire courant. Il est possible de connaître ce répertoire courant en utilisant les fonctions pwd ou getcwd et de le modifier avec la fonction chdir :
mprintf("Donnez le nom de l"'article,"+..
            " son prix, son poids et le nombre en stock\n")
while %t
  [n,name,prix,poids,nombre]=mscanf("%s %f %f %d")
  if n==4 then break,end
  mprintf("Saisie incorrecte !\n");
end
mprintf("\n%s prix=%.2fF, poids=%.2fkg, stock=%d\n",..
                          name,prix,poids,nombre)
		      
la séquence  / représente le << home directory >> de l'utilisateur, tandis que SCI/ est une abreviation pour le chemin du repertoire principal de Scilab.

3.2   Ouverture et fermeture des fichiers

Tout d'abord, avant de pouvoir accéder aux données d'un fichier, il faut créer un lien entre le fichier et Scilab. Cela se fait par l'intermédiaire de la fonction mopen qui, étant donné une chaîne de caractères contenant le chemin du fichier et quelques options, retourne un nombre, appelé identificateur ou unité logique de ce fichier, et définit le positionnement initial dans ce fichier1. La fonction mopen interface la fonction C fopen ; sa syntaxe est :
[fd,err]=mopen(file,mode,swap)
file est une chaîne de caractères contenant le chemin du fichier. Par exemple " /Scilab/dat01" Le paramètre mode permet de spécifier si le fichier doit être ouvert en lecture seule ("r"), en écriture seule ("w"), en complétion (écriture à la fin "a") ou en lecture/écrirure ("r+"). La valeur par défaut de mode est ("rb"). L'ajout du caractère "b" spécifie que les données numériques stockées dans le fichier sont représentées par leurs codes binaires. En l'abscence de cette option, les données numériques sont supposées être représentées par leur représentation formattée. Par défaut, Scilab suppose que la représentation des nombres dans les fichiers binaires correspond au format IEEE little endian 2, la conversion au format interne du processeur étant alors faite automatiquement. L'option swap=0 permet de désactiver cette conversion implicite. La fonction mopen retourne l'identificateur du fichier fd et éventuellement un indicateur d'erreur.
-->fd1=mopen("SCI/scilab.star","r")
 fd1  =
    2. 
-->[fd2,err]=mopen(TMPDIR+"/out","wb")
 err  =
    0.  
 fd2  =
    3. 
dispfiles.dia La fonction dispfiles permet d'examiner les fichiers ouverts. On remarque ici que les fichiers peuvent être de deux types C (C) ou fortran (F77). Ce dernier type existe pour permettre de manipuler les fichiers créés par ou pour d'autres logiciels écrits en fortran (voir la section 4). La fonction Scilab file permet d'acquérir les chemins des fichiers ouverts et leurs propriétés. Le nombre de fichiers pouvant être ouverts simultanément est limité, aussi il faut penser à fermer les fichiers qui ne sont plus utiles. Cela peut être fait par la fonction mclose qui doit être utilisée à la fin du traitement du fichier pour déconnecter le fichier de l'environnement Scilab. Si fd est une unité logique associée à un fichier, mclose(fd) ferme ce fichier. Il faut noter que les fichiers ouverts ne sont pas fermés automatiquement lorsqu'une erreur survient lors de l'exécution d'une instruction Scilab. L'instruction mclose(file()) ferme tous les fichiers ouverts.

3.3   Lecture binaire

La lecture et l'écriture de fichiers binaires de type C permet d'échanger des données avec la plupart des logiciels actuels. Les fichiers de sons, au format wav ou au, les fichiers d'images gif, ppm ou jpeg, les fichiers de sauvegarde de Scilab, voire même les fichiers Excel xls. Ces fichiers sont constitués d'une séquence d'octets, il est donc impératif d'en connaître la structure pour pouvoir les lire et les interpreter ! Un exemple valant mieux que mille discours, montrons comment on peut écrire en Scilab la fonction readppm qui lit les fichiers d'images de la famille PPM (couleur), PGM (niveau de gris) et PBM (noir et blanc). Ce type de fichier d'image est structuré en quatre parties :
  1. une ligne de texte donnant le type (couleur, niveau de gris ou noir et blanc) et le mode de stockage (ASCII ou binaire) ;
  2. des lignes de commentaires débutant par le caractère # ;
  3. une ligne contenant les dimensions de l'image en pixels et selon les cas une ligne contenant le nombre de couleurs ;
  4. la séquence des nombres caractérisant la couleur de chacun des pixels selon le type d'image considéré.
Donnons tout d'abord la fonction permettant d'ouvrir le fichier et de tester s'il correspond au type désiré. scilab/open_ppm.sci
unction [ftyp,fd]=open_ppm(fil)
fd=mopen(fil,"rb") //ouverture du fichier



h=mgetl(fd,1) //lecture du type
//test du type qui doit être:
//    P1, P4 : image noir et blanc
//    P2, P5 : image en niveau de gris
//    P3, P6 : image couleur
ftyp=find(h=="P"+string(1:6))
if ftyp==[] then 
  error("Ce n"'est pas un fichier de type PBM, PGM ou PPM");
end
endfunction

On retrouve ici l'usage de la fonction mopen et l'on découvre celui de la fonction mgetl qui permet de lire une ou plusieurs lignes du fichier comme du texte. Les lignes de textes sont supposées terminées par des marques de fin de ligne (pour lire une chaîne de caractères de longueur donnée on peut utiliser la fonction mgetstr).
La fonction ppm_get_comments ci-dessous lit les commentaires. scilab/ppm_get_comments.sci
function head=ppm_get_comments(fd)
head=[];
while %t
  pos=mtell(fd);//mémorise la position courante
  ligne=mgetl(fd,1) //lit une ligne comme du texte
  first=part(ligne,1) //le premier caractère de la ligne
  if first ~="#" then //est une ligne de commentaire
    mseek(pos,fd) //positionnement au point mémorisé
    break
  end	
  head=[head;ligne]
end
endfunction
Les fonctions mtell et mseek utilisées ci-dessus permettent respectivement de mémoriser la position courante dans un fichier et de la (re-)positionner.
Ensuite la fonction ppm_get_size permet de lire les dimensions de l'image et, s'il existe, le nombre de couleurs : scilab/ppm_get_size.sci
function [sz,nc]=ppm_get_size(fd,ftyp)
// Dimensions de l'image
ligne=mgetl(fd,1);
execstr("sz=["+ligne+"]");
// Nombre de couleurs
if and(ftyp~=[1,4]) then 
  ligne=mgetl(fd,1);
  execstr("nc="+ligne);
else
  nc=[];
end
endfunction
On observe ici l'usage de la fonction execstr qui permet d'évaluer une instruction Scilab donnée par une chaîne de caractères.
Enfin la fonction ppm_get_bin permet de lire la valeur des pixels dans le cas d'un stockage en binaire : scilab/ppm_get_bin.sci
function img=ppm_get_bin(fd,ftyp,sz)
select ftyp
case 4 then //blanc et noir
  t=mgeti((sz(1)*sz(2))/8,'uc',fd);	
  f=uint8(2.^(0:7))
  img=matrix([(t&f(8))/f(8);(t&f(7))/f(7);
            (t&f(6))/f(6);(t&f(5))/f(5);
	    (t&f(4))/f(4);(t&f(3))/f(3);
            (t&f(2))/f(2);(t&f(1))/f(1)],sz);
case 5 then // niveau de gris
  img=matrix(mgeti(sz(1)*sz(2),'uc',fd),sz)
case 6 then // couleur
  img=matrix(mgeti(3*sz(1)*sz(2),'uc',fd),[3,sz])
end
endfunction
Dans le cas << noir et blanc >> les pixels sont stockés à raison de 8 pixels par octet. l'opérateur & appliqué à des variables de type entier effectue le << ET >> bit à bit de ses deux opérandes. La fonction mgeti permet de lire des nombres entiers codés sur 1, 2 ou 4 octets dans un fichier binaire et de retourner un vecteur d'entiers de type correspondant. La fonction mget dont la syntaxe et le fonctionnement ressemblent à celles de mgeti permet de lire des données flottantes ou entières et les convertit automatiquement en un vecteur Scilab standard. Le premier argument de ces fonctions donne le nombre d'entiers à lire, le second le type des données que l'on souhaite lire :
Type Code Type Code
char (un octet) "c" unsigned char "uc"
short (deux octets) "s" unsigned short "us"
int (4 octets) "i" unsigned int "ui"
float (4 octets) "f" double (8 octets) "d"

Ces codes peuvent être completés par un caractère supplémentaire << l >> ou << b >> pour forcer l'interprétation << little endian >> ou << big endian >>. La visualisation graphique des images codées en niveau de gris (PGM) est réalisée simplement par la fonction : scilab/gray_image.sci
function gray_image(img)
  xset("colormap",graycolormap(double(max(img))+1))
  xset("wdim",size(img,1),size(img,2)) //taille de la fenêtre
  xsetech(arect=0*[1 1 1 1]) //suppression des marges
  Matplot(img',"020") //affichage
endfunction


bar



Figure 1: L'affichage par gray_image (Le groupe Scilab au travail)

3.4   Lecture formattée

Considérons maintenant l'exemple de la lecture des fichiers PPM ASCII pour illustrer la lecture des données formattées. L'en-tête des fichiers est la même que précédemment. La partie contenant la valeur des pixels est dans ce cas une séquence d'entiers formatés sur 1 ou 3 caractères et séparés par un caractère blanc. La fonction de lecture s'écrit alors très simplement. scilab/ppm_get_ascii.sci
function img=ppm_get_ascii(fd,ftyp,sz)
//Lit les valeurs des pixels pour une image ASCII
if or(ftyp==[4 5]) then //N&B ou niveau de gris
  img=matrix(uint8(mfscanf(sz(1)*sz(2),fd,"%i ")),sz)
else
  img=matrix(uint8(mfscanf(3*sz(1)*sz(2),fd,"%i ")),[3,sz])
end
endfunction
Cet exemple montre un usage simple de la fonction mfscanf basée sur la procédure C fscanf. Cette fonction a un comportement comparable à la fonction mscanf vue précédemment, si ce n'est de lire les valeurs dans un fichier désigné par fd plutôt que sur l'écran. Dans cet exemple, il est nécessaire de lire une grande quantité de données et l'usage d'une boucle interpretée pour effectuer cette lecture ne serait pas efficace. Cette boucle est réalisée par la fonction elle même. Le premier argument de la fonction mfscanf donne le nombre de fois ou il faut itérer le format de lecture %i. Dans cet exemple les données à lire sont toutes de même type, mais il est évidemment possible de lire des fichiers contenant des données de types hétérogènes :
Soit le fichier articles.dat:
Table_chene 3999 45.4 59 TC Table_hetre 2071 45 23 TH Chaise_chene 850.99 5.3 1000 CC Chaise_hetre 649 5 623 CH ...
Chaque ligne contient le nom d'un article, son prix, son poids, le nombre en stock et un code. La séquence d'instructions :
fd=mopen("articles.dat","r");
[n,nom,prix,poids,nombre,code]=mfscanf(-1,fd,"%s %f %f %f %d %s");
mclose(fd)
permet de lire l'ensemble des données du fichier. La valeur -1 passée comme premier argument de mfscanf indique que l'on souhaite lire toutes les lignes du fichier.

3.5   Écriture binaire et formattée

Les fonctions permettant d'écrire des données dans un fichier binaire sont similaires à celles utilisées pour la lecture, les fonctions mgetl, mget, mgetstr étant remplacées par les fonctions mputl, mput et mputstr.
Pour l'écriture formattée, la fonction mfprintf similaire à la fonction mprintf remplace la fonction mfscanf. Le script ci-dessous peut par exemple être utilisé pour générer le fichier articles.dat :
nom    = ["Table_chene";"Table_hetre";"Chaise_chene";"Chaise_hetre"];
prix   = [  3999       ; 2071        ; 850.99       ; 649  ];
poids  = [  45.4       ; 45          ; 5.3          ; 5    ];
nombre = [  59         ; 23          ; 1000         ; 623  ] ;
code   = ["TC"         ;"TH"         ;"CC"          ;"CH"  ] ;
fd=mopen("articles.dat","w");
mfprintf(fd,"%s %.2f %.1f %d %s\n",nom,prix,poids,nombre,code);
mclose(fd)

4   Entrée-sortie fortran

L'intérêt essentiel des fonctions d'entrée-sortie fortran dans Scilab est de permettre la lecture et la génération de fichiers pour communiquer avec d'autres logiciels du monde fortran. Elles peuvent aussi être utiles aux utilisateurs de l'ancienne école qui connaissent ce langage. Nous ne ferons ici que citer les fonctions correspondantes. À la différence de C, les entrées-sorties fortran, sont structurées en lignes ou en << enregistrements >>. Les unités logiques utilisées par les fonctions d'entrée-sortie fortran ne sont pas les mêmes que pour les identificateurs C. Pour les fonctions du monde fortran, les fichiers doivent être ouverts par l'instruction file("open",...) et fermés par l'instruction file("close",...). Les entrées sorties formattées sont realisées respectivement par les fonctions read et write qui utilisent des formats fortran Les fonctions d'entrée-sortie binaire de type fortran sont readb et writeb pour les données flottantes double précision (8 octets) et read4b et write4b pour les données flottantes sur 4 octets.

Serge Steer
Scilab Group, Scilab@inria.fr
1
Certaines fonctions de lecture ou écriture sur les fichiers créent ce lien automatiquement à partir du nom de fichier
2
Le format little endian correspond au mode de stockage où le bit de poids faible est stocké en premier contrairement au stockage big endian où c'est le bit de poids fort. Cette appelation provient du << Voyage de Gulliver >> de Jonathan Swift où les Big-Endians et les Little-Endians discutent pour savoir si les oeufs à la coque doivent être ouverts par le petit ou le gros bout ...!

This document was translated from LATEX by HEVEA.