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.