1. Définition du type abstrait Afficheur :
Type Afficheur (* constructeur *) CréerAfficheur : Afficheur (* opérations *) AllumeSegment : Afficheur x 1..7 -> Afficheur EteintSegment : Afficheur x 1..7 -> Afficheur SegmentAllumé : Afficheur x 1..7 -> booléen fin
2. Réalisation du type abstrait Afficheur :
Etat = (on, off) Afficheur = tableau [1..7] de Etat fonction CréerAfficheur : Afficheur lexique a : Afficheur i : 1..7 début pour i parcourant 1..7 faire a [i] <- off retourner a fin fonction AllumeSegment (a:Afficheur; s:1..7) : Afficheur début a [i] <- on retourner a fin fonction EteintSegment (a:Afficheur; s:1..7) : Afficheur début a [i] <- off retourner a fin fonction SegmentAllumé (a:Afficheur; s:1..7) : booléen début si a[i] = on alors retourner vrai sinon retourner faux fin
3. Spécification et réalisation de Eteint :
action Eteint : Afficheur (* éteint tous les segments d'un afficheur. Modifie l'afficheur, donc paramètre passé par donnée-résultat *) procédure Eteint (donnée-résultat a : Afficheur) lexique i : 1..7 début pour i parcourant 1..7 faire a [i] <- off fin fin
4. Réalisation de AfficheSymbole. qui affiche un symbole sur un afficheur, et modifie donc l'afficheur (d'où le passage par donnée-résultat) :
procédure AfficheSymbole (donnée-résultat a : Afficheur;
s : Symbole)
lexique
fini : booléen
i : 0
début
Eteint (a)
fini <- faux
i <- 1
tantque non fini faire
si s[i] = 0
alors fini <- vrai
sinon a <- AllumeSegment (a, s[i])
i <- i + 1
si i = 7 alors fini <- vrai
fin
fin
Le type concret Afficheur représente l'état de chaque segment, tandis que Symbole indique quels segments sont allumés.
5. Déclaration et valeurs initiales de la variable chiffres (on note entre accolades les valeurs successives d'un tableau), et réalisation de Afficher :
chiffres : tableau [0..9] de Symbole
chiffres [0] <- {1 2 3 5 6 7 0}
chiffres [1] <- {3 6 0 0 0 0 0}
chiffres [2] <- {1 3 4 5 7 0 0}
chiffres [3] <- {1 3 4 6 7 0 0}
chiffres [4] <- {2 3 4 6 0 0 0}
chiffres [5] <- {1 2 4 6 7 0 0}
chiffres [6] <- {1 2 4 5 6 7 0}
chiffres [7] <- {1 3 6 0 0 0 0}
chiffres [8] <- {1 2 3 4 5 6 7}
chiffres [9] <- {1 2 3 4 6 7 0}
procedure Afficher (a : Afficheur; n : entier)
début
si n >= 0 et n <= 9
alors AfficherSymbole (a, chiffres [i])
fin
6. Spécification du type abstrait Montre :
Type Montre (* constructeur *) CréerMontre : Montre (* opérations *) AfficherHeure : Montre x Heure -> Montre QuelleHeureEstIl : Montre -> Heure fin
7. Réalisation du type abstrait Montre :
type
Heure = produit
hh : 0..24
mm : 0..60
fin
Montre = produit
heure : Heure
dh, uh, dm, um : Afficheur
(* afficheurs pour la dizaine et l'unité
des heures (dh et uh) et la dizaine et
l'unité des minutes (dm et um) *)
fin
fonction CréerMontre : Montre
lexique
m : Montre
début
m.heure.hh <- 12
m.heure.mm <- 00
m.dh <- CréerAfficheur
m.uh <- CréerAfficheur
m.dm <- CréerAfficheur
m.um <- CréerAfficheur
AfficherHeure (m, m.heure)
retourner m
fin
procédure AfficherHeure (donnée-résultat m : Montre;
h : Heure)
début
m.heure <- h
(* afficher les heures. Si la dizaine vaut 0,
éteindre l'afficheur de dizaine d'heure *)
si m.heure.hh >= 10
alors Afficher (m.dh, m.heure.hh div 10)
sinon Eteint (m.dh)
Afficher (m.uh, m.heure.hh mod 10)
(* afficher les minutes. Si la dizaine vaut 0,
afficher 0 *)
Afficher (m.dm, m.heure.mm div 10)
Afficher (m.um, m.heure.mm mod 10)
fin
fonction QuelleHeureEstIl (m : Montre) : Heure
début
retourner m.heure
fin
8. Réalisation de TicTac :
procédure TicTac (donnée-résultat m : Montre) début si m.heure.hh < 23 alors m.heure.hh <- m.heure.hh + 1 sinon m.heure.hh <- 0 si m.heure.mm < 59 alors m.heure.mm <- m.heure.mm + 1 sinon m.heure.mm <- 0 AfficherHeure (m, m.heure) fin
1. Valeurs de a, b, c, d après chaque instruction. ? indique une valeur indéterminée :
instruction a b c d a, b := 1, 2 1 2 ? ? c, d := b, a + b 1 2 2 3 a, b := b, a 2 1 2 3 c, d := c - d, d - c 2 1 -1 1
2. Sémantique de l'affectation double :
a, b := e1, e2 v1 <- Val [[e1]] v2 <- Val [[e2]] Mem [Env [a]] <- v1 Mem [Env [b]] <- v2
Comme Val peut avoir un effet de bord sur les valeurs de a et b, il faut calculer v1 et v2 avant de les affecter aux variables correspondantes. C'est typiquement le cas pour l'échange de valeurs a, b := b, a.
Si l'on écrivait la sémantique de l'affectation double comme suit :
Mem [Env [a]] <- Val [[e1]] Mem [Env [b]] <- Val [[e2]]
on aurait l'équivalent de deux affectation successives. a, b := b, a serait alors identique à a := b; b := a ce qui est incorrect.
3. Spécification et réalisation de la fonction Fibonacci :
fonction Fibonacci : entier -> entier fonction Fibonacci (n : entier) : entier lexique u, v, i : entier début si n < 2 alors retourner n u, v := 0, 1 pour i parcourant 2..n faire u, v := v, u + v fin retourner v fin fonction FibonacciSimple (n : entier) : entier lexique u, v, i, tmp : entier début si n < 2 alors retourner n u <- 0 v <- 1 pour i parcourant 2..n faire tmp := u v := u u := tmp + v fin retourner v fin
La seconde réalisation nécessite une variable auxiliaire pour stocker la valeur de u. Sinon, la suite calculée serait un = un-1 + un-1.