Univ. Paris-Sud 11 - Licence MPI L1 Informatique, 2ième sem. 2017-18
TD n
o5
(Correction)Les structures
Le but de ce TD est de manipuler des structures (type struct en C++) qui est un type composé permettant de regrouper plusieurs données en une seule. L’accès aux composants (ou champs) d’une structure se fait en utilisant la “notation pointée".
Exercice 1. Le créateur d’un jeu souhaite pouvoir modéliser des personnages participants à des combats. Un personnage aura un nom, des points de vie, et un bouclier lui permettant d’arrêter les coups. La force des coups qu’il portera à son adversaire sera égale à son nombre de points de vie - 1 et il sera blessé s’il reçoit un coup d’une force supérieure à la force du bouclier qu’il porte. Un personnage blessé se verra retirer un nombre de point de vie égal à la différence entre la force du coup reçu et la force de son bouclier. La structure de données choisie pour modéliser un personnage est donc la suivante :
struct guerrier{ string nom ; int ptVie ; int bouclier ; } ;
1. Écrire la procédure créeGuerrier qui permet d’initialiser un personnage, sachant qu’il doit disposer au départ d’exactement 10 points à répartir entre les points de vie du personnage (au moins deux points) et la force de son bouclier. Par exemple, on devra pouvoir saisir le nom du personnage, par exemple, "Elisa", et lui donner 7 points de vie.
Dans ce cas, la procédurecréeGuerrier devra lui affecter automatiquement un bouclier d’une force égale à 3 (10 - 7).
Vous pouvez réutiliser, sans la redéfinir ni la réaliser, la fonction ci-dessous, qui reprend et étend avec un paramètre supplémentaire, celle vue dans le TD1,
int litValeurBornee(string texteAEcrire, int min, int max);
Cette fonction permet, après avoir affiché letexteAEcrireexplicitant la valeur attendue.
de saisir une valeur auprès de l’utilisateur, de vérifier qu’elle est bien comprise entre un Minet un Max, puis de la renvoyer quand elle respecte les bornes données.
Correction :
void creeGuerrier(guerrier &g) {
cout << "donner le nom de votre personnage";
cin >> g.nom ;
g.ptVie = litValeurBornee("nbre de point de vie", 2, 10);
g.bouclier = 10 - g.ptVie;
}
2. Spécifier et réaliser la procédure afficheGuerrierpermettant d’afficher l’état d’un guer- rier, i.e. son nom, et ses différentes propriétés.
Correction :
void afficheGuerrier(guerrier g) {
cout << "personnage : " << g.nom << endl;
cout << "ptdeVie : " << g.ptVie << endl;
cout << "bouclier : " << g.bouclier << endl;
}
3. Spécifier et réaliser la fonction forceCoup qui permet de retourner la force du coup porté par un guerrier vivant, calculée comme égale à son nombre de points de vie - 1.
Correction :
int forceCoup(guerrier g) { return g.ptVie - 1;
}
4. Spécifier et réaliser la procédure reçoitCoup qui met à jour l’état d’un guerrier qui reçoit un coup d’une force donnée.
Correction :
void recoitCoup(guerrier &g, int f) { int temp;
if (f > g.bouclier) {
temp = g.ptVie + g.bouclier - f;
if (temp >= 0) G.ptVie = temp;
else g.ptVie = 0;
} }
5. On suppose déjà réalisée la procédure
void initialiseGuerrierAutomatique(guerrier G1; guerrier &G2);
qui permet au concepteur de créer le guerrier G2 qui combattra le guerrier G1 créé par l’utilisateur du jeu. Réaliser le programme principal qui crée les deux guerriers, les affiche, enchaîne les coups qu’ils se portent jusqu’à ce que l’un des deux ne soit plus en état de se battre puis affiche le nom du gagnant et ses points de vie.
Correction :
int main() {
guerrrier g1, g2;
creeGuerrier(g1);
initialiseGuerrierAutomatique(g1, g2);
while (g1.ptVie > 1 and g2.ptVie > 1) { afficheGuerrier(g1);
afficheGuerrier(g2);
recoitCoup(g2, ForceCoup(g1));
if (g2.ptVie >= 1) alors recoitCoup(g1, ForceCoup(g2));
}
cout << "Gagnant : ";
if (g1.ptVie > g2.ptVie) afficheGuerrier(g1);
else afficheGuerrier(g2);
}
Exercice 2. Une entreprise vend des fournitures de bureau (crayon, gomme, ciseaux,...).
Chaque fourniture stockée dans la réserve est identifiée par un code numérique unique (ex : 345), un libellé exprimé sous la forme d’une chaîne de caractères (ex. stylo feutre pointe fine marque Boc), un prix d’achat unitaire au fournisseur (ex. 1,5 euro), le nombre d’items achetés au fournisseur et le nombre d’items déjà vendus.
Chaque fin d’année, l’entreprise effectue son inventaire, i.e. décompte pour chaque fourni- ture, le nombre d’items théoriquement en stock (c.à.d. le nombre d’items achetés au fournisseur moins le nombre d’items vendus) puis calcule le montant total du stock (somme des prix d’achat unitaire multipliés par les nombres d’items théoriquement en stock).
On vous demande de programmer les fonctions et procédures suivantes. À chaque question, vous devrez également programmer une petite procédure de test quand c’est possible ou de démonstration sinon.
1. une structureFourniture adapté à la représentation des informations apparaissant dans l’énoncé ci-dessus ;
2. la procédure permettant de saisir (lire au clavier) les information relatives à une fourniture et de les transmettre en résultat ;
3. la procédure permettant d’afficher les informations relatives à une fourniture donnée ; 4. la procédure qui met à jour une fourniture f donnée, quand une vente de n unités de
cette fourniture vient d’être effectuée ;
5. la procédure qui pour une fournituref donnée, calcule et transmet en résultat le nombre d’items en stock et le montant correspondant ;
6. une structure Catalogue permettant de représenter l’ensemble des fournitures (au plus 500) vendues par l’entreprise.
7. la procédure permettant de rajouter une nouvelle fournituref donnée dans un catalogue cdonné et supposé non plein.
8. la procédure ou fonction bilan qui étant donné un catalogue c, affiche pour chaque fourniture, son libellé, le nombre d’items en stock et le montant correspondant, puis enfin, affiche la valeur totale du stock ;
9. la procédure permettant de retirer une fourniture de code donné d’un catalogue cdonné.
Correction :
#i n c l u d e <i o s t r e a m >
#i n c l u d e <cmath>
#i n c l u d e < s t r i n g . h>
u s i n g namespace s t d ;
#d e f i n e ASSERT( t e s t ) i f ( ! ( t e s t ) ) c o u t << " T e s t f a i l e d i n f i l e " << __FILE__ \
<< " l i n e " << __LINE__ << " : " #t e s t << e n d l s t r u c t f o u r n i t u r e {
s t r i n g l i b e l l e ; f l o a t p r i x ;
i n t code , nbAchat , nbVendu ; } ;
v o i d l i t F o u r n i t u r e ( f o u r n i t u r e &f ) {
c o u t << " e n t r e z l e code , l e l i b e l l e e t l e p r i x "<< e n d l ; c i n >> f . c o d e >> f . l i b e l l e >> f . p r i x ;
do {
c o u t << "nb a c h e t e s e t nb vendus " << e n d l ;
c i n >> f . nbAchat >> f . nbVendu ;
} w h i l e ( ( f . nbAchat < 0 ) o r ( f . nbVendu > f . nbAchat ) ) ; }
v o i d e c r i t F o u r n i t u r e ( s t r u c t f o u r n i t u r e f ) {
c o u t << " l a f o u r n i t u r e " << f . l i b e l l e << " de c o d e " << f . c o d e << " commandee "
<< f . nbAchat <<" f o i s , a e t e vendue " << f . nbVendu <<" f o i s " <<e n d l ; }
// s e r a p p e l e r l o r d r e dans l e q u e l l e s e l e m e n t s o nt e t e i n t r o d u i t s // c e s deux v a r i a b l e s s o n t d e s v a r i a b l e s g l o b a l e s pour l e s demos f o u r n i t u r e f 1= {"gomme" , 1 . 1 0 , 1 0 1 , 2 0 , 4 } ;
f o u r n i t u r e f 2= {" c r a y o n " , 0 . 5 0 , 1 0 2 4 , 2 0 , 7 } ; v o i d d e m o A f f i c h e ( ) { e c r i t F o u r n i t u r e ( f 1 ) ; } v o i d maj ( f o u r n i t u r e &f , i n t n ) { f . nbVendu+=n ; } v o i d demoMaj ( ) {
maj ( f 1 , 2 ) ; e c r i r e F o u r n i t u r e ( f 1 ) ; }
v o i d s t o c k ( f o u r n i t u r e f , i n t &n , f l o a t &montant ) { n = f . nbAchat−f . nbVendu ;
montant = n ∗ f . p r i x ; } v o i d demoStock ( ) {
f l o a t m; i n t n ; s t o c k ( f 1 , n ,m) ;
cout< <" s t o c k de f 1 : " << n << " en euro , ca r e p r e s e n t e " << m << e n d l ; } c o n s t i n t TAILLE=500;
s t r u c t c a t a l o g u e {
f o u r n i t u r e tab [ TAILLE ] ; i n t nb ;
} ;
v o i d a j o u t e A u C a t a l o g u e ( c a t a l o g u e &c , f o u r n i t u r e f ) { c . ta b [ c . nb]= f ; // marquer l e s deux e t a p e s c . nb = c . nb +1;
}
v o i d b i l a n ( c a t a l o g u e c ) { // ou ( c o n s t c a t a l o g u e &c ) i n t n ; f l o a t m, sum = 0 ; f o u r n i t u r e f ; f o r ( i n t i =0; i < c . nb ; i ++){
f = c . ta b [ i ] ; s t o c k ( f , n ,m) ;
c o u t << " i l y a " << n << " "<< f . l i b e l l e
<< " en euro , ca r e p r e s e n t e " << m << e n d l ; sum += m;
}
c o u t << " l e s t o c k t o t a l vaut " << sum << e n d l ; }
v o i d demoBilan ( ) {
c a t a l o g u e c ; c . nb =0;
a j o u t e A u C a t a l o g u e ( c , f 1 ) ; a j o u t e A u C a t a l o g u e ( c , f 2 ) ; b i l a n ( c ) ;
}
v o i d r e t i r e C a t a l o g u e ( c a t a l o g u e &c , i n t c o d e ) { i n t i =0;
w h i l e ( i <c . nb and c . ta b [ i ] . c o d e != c o d e ) { i ++;}
i f ( i==c . nb ) {
c o u t << " l a f o u r n i t u r e de c o d e " << c o d e << "n e x i s t e pas " ;
} e l s e { // on supprime l a i−ieme donc on d e c a l e l e r e s t e du t a b l e a u f o r ( i n t j=i ; j <c . nb ; j ++) c . ta b [ j ] = c . tab [ j + 1 ] ;
c . nb = c . nb −1;
} }
v o i d d e m o R e t i r e ( ) {
c a t a l o g u e c ; c . nb =0;
a j o u t e A u C a t a l o g u e ( c , f 1 ) ; a j o u t e A u C a t a l o g u e ( c , f 2 ) ; b i l a n ( c ) ;
r e t i r e C a t a l o g u e ( c , 1 0 2 4 ) ; b i l a n ( c ) ;
}
i n t main ( ) { d e m o A f f i c h e ( ) ; demoMaj ( ) ; demoStock ( ) ;
d e m o R e t i r e ( ) ; r e t u r n 0 ; }