• Aucun résultat trouvé

Analyse de LIRE_ET_EVALUER .1 LIRE_ET_EVALUER : Comment faire ?

3 Les limites de l'approche descendante

4. Des chiffres et des lettres

4.16 Analyse de LIRE_ET_EVALUER .1 LIRE_ET_EVALUER : Comment faire ?

Le point le plus important est le choix de la forme sous laquelle le nombre fourni par l'utilisateur sera codé; on sait que si l'on choisit de considérer la donnée comme un réel, aucune vérification du fait que les caractères sont bien des chiffres n'est possible : ou ce que l'utilisateur fournit est bien l'écriture d'un réel et la donnée est acceptée, ou ce n'est pas le cas et le programme "se plante". L'unique solution consistera forcément à lire le nombre fourni par l'utilisateur comme une chaîne de caractères et à utiliser à bon escient la procédure de transformation d'une chaîne en un nombre. L'essentiel de la démarche va donc consister à lire la chaîne de caractères fournie par l'utilisateur et à explorer cette dernière pour en extraire la sous-chaîne (éventuellement vide) reprenant la partie entière du nombre et la sous-chaîne (éventuellement vide) représentant sa partie décimale. En cas d'erreur, la lecture sera reprise.

Les étapes seront donc les suivantes :

- Lire comme une chaîne de caractères le nombre fourni par l'utilisateur. - Si la longueur de cette chaîne est nulle ou dépasse 10, il y a une erreur.

- En l'absence d'erreur, on va explorer la chaîne, caractère après caractère, en bâtissant chiffre après chiffre, la chaîne constituant la partie entière (qui peut être vide) puis la chaîne constituant la partie décimale (qui peut être vide également); tout écart par rapport à l'écriture correcte d'un réel et par rapport aux spécifications (partie entière comportant au plus 6 caractères-chiffres, partie décimale en comportant au plus 3) sera signalé comme une erreur.

- Tout ce processus (lecture, validation, décomposition) sera repris jusqu'à ce que plus aucune erreur n'apparaisse.

- La chaîne constituant la partie entière, puis celle constituant la partie décimale (complétée par des 0 terminaux pour avoir 3 caractères, puisqu'on veut la partie décimale exprimée en millièmes) seront alors transformées grâce à la procédure val (Cf. p. 211) en des nombres

entiers.

4.16.2 LIRE_ET_EVALUER : Comment faire faire ?

La connaissance des outils de traitement des chaînes de caractères (string) est ici essentielle. On consultera pa exemple l'annexe page 207 à ce propos.

Répéter

Erreur ← faux Erreur de type booléen

Lis et place dans ChaineLue ChaineLue de type string[20]

VERIFIER_ET_SCINDER ChaineEntiere de type string[6], ChaineDecimale de type string[3]

jusqu'à ce que pas Erreur

Si ChaineEntiere est vide alors (1) ChaineEntiere ← '0'

Tant que longueur de ChaineDecimale < 3 (2)

Accoller '0' au bout de ChaineDecimale

Transformer ChaineEntiere en l'entier PartieEntiere (3)

Transformer ChaineDecimale en l'entier PartieDecimale avec

VERIFIER_ET_SCINDER

ChaineLue

de type chaîne

Scinder la chaîne contenue dans ChaineLue en la partie entière (placée dans ChaineEntiere) et la partie décimale (placée dans ChaineDecimale). Si une erreur est rencontrée (partie entière de plus de 6 chiffres, partie décimale de plus de 3, symboles ne constituant ni des chiffres, ni un unique séparateur décimal) Erreur sera placée à vrai; elle prendra la valeur faux dans le cas où tout est correct.

ChaineEntiere, ChaineDecimale de type chaîne Erreur de type booléen avec Avant Après - ChaineLue, de type chaîne (string[20]), au contenu

quelconque, fourni par l'utilisateur.

- ChaineEntiere, de type chaîne (string[6]), au contenu quelconque.

- ChaineDecimale, de type chaîne (string[3]), au contenu quelconque.

- Erreur, de type booléen contient faux.

- ChaineLue, non modifiée

- ChaineEntiere, de type chaîne, contient la succession des caractères-chiffres constituant la partie entière du nombre (au plus 6 caractères et éventuellement vide) pour autant que

Erreur soit faux; sinon (si Erreur est vrai) le contenu de ChaineEntiere est quelconque.

- ChaineDecimale, de type chaîne, contient la succession des craractères-chiffres constituant la partie décimale du nombre (au plus 3 caractères et éventuellement vide) pour autant que

Erreur soit faux; sinon (si Erreur est vrai) le contenu de ChaineDecimale est quelconque.

- Erreur, de type booléen, vrai si une erreur ou une non conformité aux spécifications a été détectée dans l'écriture du nombre contenu dans ChaineLue.

Quelques remarques sont indispensables :

(1) En l'absence de précisions sur le comportement de la procédure Pascal val chargée de transformer une chaîne en un nombre, j'ai préféré, lorsque la chaîne PartieEntiere est vide, ne pas risquer d'erreur en plaçant alors explicitement dans PartieEntiere le caractère "0".

Il semble bien (en tout cas dans certaines implémentations de Pascal) que dans le cas d'une chaîne vide, val fournisse comme nombre correspondant 0, ce qui rend inutile le test et l'éventuelle affectation du caractère "0" à ChaineEntiere.

(2) Le nombre constituant la partie décimale devra exprimer des millièmes. Il faut donc que la chaîne ChaineDecimale soit constituée de chiffres tels que l'application de val à cette chaîne fournisse bien le nombre de millièmes. Ainsi, si ChaineLue contenait "0.9", la chaîne

ChaineDecimale contiendrait le caractère "9". L'application de val fournirait alors dans PartieDecimale l'entier 9, alors que c'est 900 (millièmes) qui devrait y figurer. Le fait de

compléter ChaineDecimale par des 0 terminaux (jusqu'à avoir une chaîne de 3 caractères), transformera, dans l'exemple évoqué, cette chaîne en "900"; dans ce cas val fournira bien la valeur attendue.

Notons au passage que nous postulons de toute manière un comportement adéquat de la procédure val lorsque ChaineDecimale contient des 0 initiaux. On pourrait en effet, si ChaineLue contient "0.09", retrouver à l'issue de VERIFIER_ ET_SCINDER une ChaineDecimale contenant "09", puis "090" après complétion par un "0" terminal. La procédure val néglige heureusement le "0" initial et place bien dans PartieDecimale le nombre 90.

(3) C'est, je l'ai déjà signalé, la procédure val qui se charge de la transformation d'une chaîne en nombre (entier ou réel). Cette procédure comporte en réalité 3 paramètres (Cf. page 211) : - le premier, de type chaîne et de genre valeur, accueille en entrée la chaîne à transformer

en nombre;

- le second, de type entier ou réel et de genre variable, fournit dans la variable qui y sera associée le nombre correspondant à la chaîne fournie dans le premier paramètre;

- le troisième, de type entier et de genre variable, fournit dans la variable entière associée une valeur nulle lorsque la transformation a pu être menée à bien (parce que la chaîne fournie dans le premier paramètre représente bien un nombre, entier ou réel, correctement écrit). Lorsque la valeur de ce troisième paramètre (variable) est non nulle, elle désigne le numéro du premier caractère à partir duquel la chaîne passée comme premier paramètre n'est plus l'écriture correcte d'un entier ou d'un réel.

En ce qui nous concerne, l'exécution préalable de VERIFIER_ET_SCINDER assure que

ChaineEntiere et ChaineDecimale représentent bien des nombres. Dès lors la vérification

effectuée par val est inutile. Il faut pourtant bien disposer d'une variable qui sera associée au troisième paramètre de val, même si cette variable est inutilisée.

Dès lors, les deux dernières instructions de la marche à suivre proposée vont devenir :

val(ChaineEntiere, PartieEntiere, NeSertArien) NeSertARien de type entier

val(ChaineDecimale, PartieDecimale, NeSertARien)

Et nous voilà, une fois de plus en mesure de fournir la procédure correspondante.

4.16.3 LIRE_ET_EVALUER : Comment dire ? procedure LIRE_ET_EVALUER;

(* Elle fait lire un nombre (sous la forme d'une chaîne de caractères) et vérifie qu'il a bien les caractéristiques voulues ( au plus 6 chiffres pour la partie entière et 3 chiffres pour la partie décimale. Elle fait placer la succession des chiffres de la partie entière dans PartieEntiere et la succession des chiffres de la partie décimale dans PartieDecimale par appel de la procédure VERIFIER_ET_SCINDER. Les erreurs éventuelles sont détectées et la lecture est alors recommencée *)

var ChaineLue : string[25];

(* succession des caractères du nombre à écrire *)

ChaineEntiere : string[6];

(* succession des chiffres de la chaîne constituant la partie entière *)

ChaineDecimale : string[3];

(* succession des chiffres de la chaîne constituant la partie décimale *)

NeSertARien

: integer;

Erreur : boolean;

procedure VERIFIER_ET_SCINDER;

(* Elle explore ChaineLue et ajoute les caractères successivement extraits au bout de

ChaineEntiere ou de ChaineDecimale selon qu'on est en train d'explorer la partie entière du

nombre ou sa partie décimale. En cas d'erreur, le booléen Erreur est placé à vrai. *)

begin repeat

Erreur:=false; Clrscr;

write('Donnez le nombre à écrire : '); readln(ChaineLue);

VERIFIER_ET_SCINDER; until not Erreur;

if ChaineEntiere = '' then ChaineEntiere:='0';

(* on complète éventuellement la partie décimale par des 0 pour obtenir un "nombre" (une chaîne) à 3 chiffres *)

while length(ChaineDecimale) < 3 do

ChaineDecimale:= ChaineDecimale + '0'; (* + sert à concaténer les chaînes *)

val(ChaineEntiere,PartieEntiere,NeSertArien); val(ChaineDecimale,PartieDecimale,NeSertARien); end;