DEUG MIAS M2


Examen - 5 septembre 1997 - corrigé



[Sujet de l'examen]



Problème

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
 

Exercice

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.


Michel Beaudouin-Lafon, mbl@lri.fr