Algorithmes et Structures de Données 2
Thèmes abordés
Algorithmes et Structures de Données 2
Thèmes abordés
INFORMATIQUE
Dr
Agnès
LETOUZEY
EC
TC
P324
-‐
ALGORITHMIQUE
ET
STRUCTURES
DE
DONNEES
2
Sommaire
SOMMAIRE
SOMMAIRE
...............................................................................................................................................................
3
II.
EN
ALGORITHMIQUE
La
déclaration
d’une
variable
chaîne
de
caractères
se
fait
de
la
façon
suivante
:
Chaîne nom_variable
On
peut
saisir
ou
afficher
le
contenu
d’une
variable
de
type
chaîne
à
l’aide
des
instructions
saisir
et
afficher.
On
peut
accéder
à
chaque
caractère
d’une
variable
de
type
chaîne
en
spécifiant
la
position
de
ce
caractère.
Pour
des
raisons
de
simplicité
de
traduction
en
langage
C,
le
premier
caractère
se
trouve
en
position
0.
Il
est
aussi
possible
d’extraire
une
partie
d’une
chaîne
de
caractères,
à
l’aide
de
la
primitive
sous-‐chaîne.
Les
opérateurs
de
comparaison
:
=, ≠, <, ≤, >, ≥
sont
utilisables
;
la
relation
d’ordre
est
l’ordre
alphabétique.
L’opérateur
+ permet
de
concaténer
deux
chaines
(mettre
bout
à
bout).
Soit la déclaration suivante,
Chaîne nom
Alors
nom [ i ] :
désigne le i+1ième caractère de la chaîne nom.
sous-chaîne ( nom , i , j) :
désigne la chaîne contenue dans la chaîne nom, commençant au i+1ième caractère de nom et contenant j caractères.
long (nom ) :
indique le nombre de caractères de la chaîne nom.
III. EN LANGAGE C
III.1.
DECLARATION
En
C++,
il
existe
un
type
permettant
de
manipuler
de
façon
simple
des
chaines
de
caractères
:
affectation,
concaténation,
recherche
de
sous-‐chaînes,
insertion
ou
suppression
de
sous-‐chaines…
ce
type
est
le
type
string.
Une
variable
(ou
un
objet)
de
type
string
contient
une
suite
de
caractères,
le
nombre
de
ces
caractères
peut
évoluer
au
cours
de
l’exécution.
Comme
toute
autre
variable
on
peut
déclarer
seulement
ou
déclarer
et
initialiser.
Les
diverses
syntaxes
sont
illustrées
ci-‐
dessous.
string ch ; // déclaration seule, taille de la chaine = 0
string nombis="chats" ; // affectation de chats
string ch1("Bonjour chez vous") ; // affectation de Bonjour chez vous
string ch2(10,'*') ; // affectation d’une suite de 10 *
string ch3(nombis); // affectation de nombis
III.2.1.
Longueur
:
On
accède
aux
nombres
de
caractères
de
la
chaîne
par
l’intermédiaire
des
fonctions
size()
ou
length()
cout << nombis.size() << endl; // affiche 5
cout << ch1.size() << endl ; // affiche 17
cout << ch2.length() << endl ; // affiche 10
cout << ch3.length() << endl ; // affiche 5
#include <string>
string nom="bonjour", nombis ;
nombis.insert(7," de");
nombis.erase(7,3);
nombis.erase(7);
nombis.replace(3, 3, "soi") ;.
nombis.replace(3, 2, "ne nuit") ;
fin
IV. EXERCICES
IV.1.
EXERCICE
1
Ecrivez
un
programme
permettant
à
l'utilisateur
de
saisir
un
mot
au
clavier,
puis
affiche
le
mot
au
pluriel.
Utilisez
les
règles
suivantes
(Cf.
espacefrancais.com:
http://bit.ly/ejEifZ):
1. On
forme
généralement
le
pluriel
des
noms
en
ajoutant
un
s
au
singulier.
Exemple
:
Le
chien
¢
les
chiens.
2. Les
noms
en
-‐au,
-‐eau,
-‐eu
prennent
un
x
au
pluriel.
Exemple
:
Un
tuyau
¢
des
tuyaux,
le
seau
¢
les
seaux...
Exceptions
:
Quatre
noms
:
landau,
sarrau,
bleu,
pneu
font
exception
et
prennent
un
s
:
les
landaus,
les
sarraus,
les
bleus,
les
pneus.
3. Les
noms
en
-‐ou
prennent
un
s
au
pluriel.
Exemple
:
Le
verrou
¢
les
verrous.
Exceptions
:
Sept
noms:
bijou,
caillou,
chou,
genou,
hibou,
joujou,
pou
font
exception
et
prennent
x
au
pluriel.
4. Les
noms
en
-‐ail
prennent
un
s
au
pluriel.
Exemple
:
Le
chandail
¢
les
chandails.
Exceptions
:
Sept
noms
:
bail,
corail,
émail,
soupirail,
travail,
vantail,
vitrail
font
exception
et
changent
-‐ail
en
-‐aux
(sans
e).
5. Les
noms
en
-‐al
font
leur
pluriel
en
-‐aux
(sans
e).
Exemple
:
Le
cheval
¢
les
chevaux,
le
mal
¢
les
maux.
Exceptions
:
Quelques
noms
:
bal,
carnaval,
chacal,
festival,
récital,
régal
font
exception
et
prennent
un
s
au
pluriel.
Seul
idéal
fait
idéals
ou
idéaux.
6. Les
noms
terminés
par
s,
x
ou
z
au
singulier
ne
changent
pas
au
pluriel.
Exemple
:
le
poids
¢
les
poids,
le
silex
¢
les
silex,
le
nez
¢
les
nez.
Attention,
vous
traiterez
les
règles
au
fur
et
à
mesure,
dans
l’ordre
qui
vous
semble
le
plus
simple.
En
particulier,
vous
avez
intérêt
à
commencer
par
la
règle
6.
Testez votre programme au fur et à mesure de la prise en compte des règles.
IV.2.
EXERCICE
2
On
souhaite
effectuer
la
saisie
d’une
information
à
crypter.
Pour
recueillir
cette
information
on
utilise une
chaîne
de
caractères
appelée
Phrase.
Écrire
un
programme
permettant
la
saisie
par
l’utilisateur
d’une
chaîne
de
caractères
qui
sera
stockée
dans
la
variable
Phrase,
puis
affiche
le
nombre
de
caractères
de
la
chaîne
saisie,
et
enfin
affiche
chaque
caractère
de
cette
chaîne
en
les
séparant
par
des
espaces.
On
souhaite
effectuer
un
cryptage
simple
de
l’information
contenue
dans
la
variable
Phrase.
On
supposera
ici
que
la
phrase
ne
contient
que
des
lettres
minuscules
(de
a
à
z)
et
des
espaces.
On
transformera
chaque
caractère
de
la
manière
suivante
:
le
caractère
’a’
est
transformé
en
’b’,
’b’
est
transformé
en
’c’,
’c’
est
transformé
en
’d’,
.
.
.
,
’z’
est
transformé
en
’a’.
Les
caractères
espace
(’
’)
ne
sont
pas
transformés.
En enrichissant le programme écrit précédemment, écrire un programme qui réalise cette transformation.
IV.3.
EXERCICE
3
Ecrire
un
programme
permettant
à
l'utilisateur
de
saisir
un
mot
au
clavier,
puis
affiche
si
ce
mot
est
un
palindrome
ou
non
(un
palindrome
est
un
mot
identique
dans
les
deux
sens
de
lecture
:
ressasser,
radar,
etc.).
IV.4.
EXERCICE
4
Ecrire
un
programme
permettant
à
l'utilisateur
de
saisir
deux
mots
au
clavier,
puis
affiche
si
ces
deux
mots
sont
des
anacycliques
ou
non
(un
anacyclique
est
un
mot
pouvant
se
lire
dans
les
deux
sens
:
noel
et
leon,
ressac
et
casser,
etc.).
I.
EN
ALGORITHMIQUE
Le
type
article
ou
structure
permet
donc
de
désigner
sous
un
même
nom
des
données
de
type
différent.
Lors
de
sa
déclaration,
on
nommera
chacun
des
éléments
appelés
champs
de
la
structure.
L’accès
aux
éléments
d’une
variable
structurée
se
fait
par
la
désignation
du
nom
du
champ.
Par
exemple,
on
peut
représenter
l’ensemble
des
caractéristiques
de
clients
d’une
entreprise
par
le
type
article
suivant
:
type structuré unclient début
Chaîne : nom
Entier : age
Réel : remise
fin
On
pourra
ensuite
déclarer
des
variables
de
type
structuré
unclient,
par
exemple,
si
monsieur
est
une
variable
de
type
unclient,
on
effectuera
la
déclaration
suivante
:
unclient
monsieur.
nom, age
et
remise
sont
les
champs
auxquels
on
peut
avoir
accès
simplement
en
les
nommant.
Sur
l’exemple
de
déclaration
de
variable
précédent,
on
aura
accès
à
la
remise
concédée
au
client
monsieur
en
écrivant
monsieur.remise.
La
notation
utilisée
ici
pour
désigner
les
champs
(point
.)
n’est
pas
la
seule
existante.
Attention
:
Il
ne
faut
pas
confondre
le
type
et
les
variables.
Dans
l’exemple
précédent,
unclient
est
un
nom
de
type,
qui
s’apparente
à
entier
ou
réel
ou
…
Pour
manipuler
des
données
de
ce
nouveau
type,
il
faut
les
déclarer.
II. EN LANGAGE C
III. EXERCICES
Fin
Le
nombre
de
parts
retenu
pour
le
calcul
de
l’impôt
sur
le
revenu
(cas
général
simplifié)
est
calculé
en
utilisant
les
règles
suivantes
:
Pour
une
personne
mariée
ou
pacsée
le
nombre
de
parts
est
de
2,
dans
les
autres
situations,
le
nombre
de
parts
est
de
1.
Les
deux
premiers
enfants
conduisent
à
une
demi-‐part
supplémentaire
chacun,
les
suivants
une
part
supplémentaire.
Ainsi,
une
personne
mariée
avec
deux
enfants
à
charge
dispose
de
3
parts,
une
personne
célibataire
avec
un
enfant
à
charge
dispose
de
1.5
part,
une
personne
mariée
avec
trois
enfants
à
charge
dispose
de
4
parts…
Ecrire
un
algorithme
puis
le
programme
C
qui
saisit
les
informations
associées
à
une
personne,
calcule
son
nombre
de
parts
et
affiche
son
nom
suivi
d’un
message
indiquant
le
nombre
de
parts.
Ecrire
un
algorithme
puis
le
programme
C
qui
met
à
jour
les
informations
associées
à
deux
équipes
à
l’issue
d’un
match
les
ayant
opposées.
Les
informations
saisies
au
clavier
seront
donc
nom,
nombre
de
points
et
différence
courants
des
deux
équipes
nombre
de
points
marqués
par
chaque
équipe
dans
le
match
nombre
d’essais
marqués
par
chaque
équipe
dans
le
match.
Les
nouvelles
caractéristiques
des
deux
équipes
seront
affichées
à
l’issue
de
la
mise
à
jour.
Ecrire
un
algorithme
et
le
programme
C
correspondant
qui
saisit
les
informations
associées
à
un
véhicule
et
affiche
son
nom
suivi
d’un
message
indiquant
le
permis
nécessaire
à
son
utilisation.
b.Car = d ?
non Critiquez
l’algorithme.
oui
b.Nb ← b.Nb + 1
b.Val ← b.Val + c
non
d≠‘*’?
oui
fin
Ecrire
un
algorithme
et
le
programme
C
correspondant
qui
saisit
les
informations
associées
à
un
polygone
et
qui
affiche
son
aire
et
son
périmètre.
Ecrire
un
algorithme
et
le
programme
C
correspondant
qui
saisit
un
rectangle
et
un
point
et
qui
affiche
:
à
l’intérieur,
à
l
‘extérieur
ou
sur
le
bord
en
fonction
de
la
position
du
point
par
rapport
au
rectangle.
Ecrire
un
programme
C
utilisant
ce
type
de
données
et
permettant
à
l'utilisateur
de
Saisir
2
nombres
complexes
dans
l'une
ou
l'autre
des
écritures
pour
chacun
des
nombres,
si
la
forme
algébrique
(respectivement
géométrique)
est
saisie,
mettre
à
jour
la
forme
géométrique
(respectivement
algébrique)
par
le
calcul.
Faire
la
somme
de
ces
deux
nombres
complexes
et
d'afficher
le
résultat
sous
forme
algébriques
et
géométriques,
Faire
le
produit
de
ces
deux
nombres
complexes
et
d'afficher
le
résultat
sous
forme
algébrique
et
géométrique.
Rappel
:
Le
calcul
de
la
somme
est
plus
facile
en
algébrique,
celui
du
produit
en
géométrique.
Formules
:
r = x 2 + y2 et θ = Arctg(y / x)
x = r cos(θ ) et y = r sin(θ )
z1 + z2 = x1 + x2 + i(y1 + y2 )
z1 × z2 = r1r2 eθ1+θ2 ou z1 × z2 = x1 x2 − y1 y2 + i(x1 y2 + x2 y1 )
Ecrire
un
algorithme
qui
saisit
les
informations
associées
à
un
article,
affiche
son
nom
suivi
d’un
message
indiquant
le
coût
du
stock
de
cet
article,
puis
affiche
un
message
d’alerte
si
cet
article
doit
être
réapprovisionné.
Ecrire un algorithme permettant de déclarer une variable de type Point, de saisir ses champs et de l'afficher.
Définir
une
structure
Droite
comprenant
deux
membres
de
type
point,
puis
compléter
l'algorithme
précédent
afin
de
déclarer,
saisir
et
afficher
une
variable
de
type
Droite.
Compléter l'algorithme précédent afin de vérifier que le point est sur la droite ou non et afficher le résultat.
Compléter
l'algorithme
afin
de
créer
deux
droites,
d’afficher
leurs
caractéristiques
puis
vérifier
si
les
droites
sont
parallèles
ou
perpendiculaires
et
afficher
le
résultat.
La
Figure
3
suivante
représente
un
tableau
à
2
dimensions,
qui
peut
être
vu
soit
comme
une
matrice
de
taille
4
lignes
x
5
colonnes,
soit
comme
un
ensemble
de
4
tableaux
de
5
éléments.
On
accède
à
un
élément
d’un
tableau
à
2
dimensions
en
utilisant
2
indices.
Par
exemple,
l’élément
d’indices
[3,
2]
peut
être
vu
comme
l’élément
de
la
matrice
situé
à
la
ligne
d’indice
3
(4ème
ligne)
et
à
la
colonne
d’indice
2
(3ème
colonne).
Cet
élément
vaut
6.5.
Il
peut
aussi
être
vu
comme
le
3ème
élément
du
4ème
tableau
de
5
éléments.
0
1
2
3
4
Il
n’y
a
pas
de
limite
au
nombre
de
dimensions
d’un
tableau
(dans
la
limite
de
la
taille
mémoire
disponible).
Ainsi,
l’accès
à
un
élément
dans
un
tableau
à
n
dimensions
(où
n
est
un
entier
naturel
non
nul)
se
fait
à
l’aide
de
n
indices
(un
indice
pour
chaque
dimension).
L’ordre
des
indices
est
capital.
Par
exemple,
dans
le
tableau
de
dimension
2
présenté
à
la
Figure
3,
l’élément
d’indices
[2
,
3]
vaut
11.4
alors
que
l’élément
d’indices
[3
,
2]
vaut
6.5.
II.1.
EN
ALGORITHMIQUE
Lors
de
la
déclaration
d’une
variable
de
type
tableau,
on
devra
préciser
le
type
de
ses
éléments
et
la
taille
du
tableau,
celle-‐ci
sera
nécessairement
CONSTANTE
et
devra
être
précisée.
On
utilisera
une
déclaration
de
la
forme
:
réel mat [10 ; 10] , entier vect [0 .. 4], entier v [5]
Il
existe
beaucoup
d’autres
formalismes.
L’essentiel
est
que
le
type
des
éléments
composant
le
tableau,
la
taille
(en
supposant
que
l’indice
de
début
est
0,
ou
encore
l’indice
de
début
et
de
fin
...),
et
le
nom
du
tableau
figurent
dans
la
ligne
de
déclaration.
L’accès
aux
éléments
du
tableau
se
fait
par
l’utilisation
d’un
(ou
plusieurs)
indice
entier
qui
doit
appartenir
au
domaine
de
variation
précisé
dans
la
déclaration
du
tableau.
L’indice
peut
être
une
constante
entière,
une
variable
entière,
une
expression
entière.
Par
exemple,
soit
les
déclarations
suivantes
:
réel vect [10]
réel mat [20 ; 10]
entiers : i, j
alors vect [i] : désigne le i+1ème réel du tableau vect,
vect [2] : désigne le 3ème réel du tableau vect,
vect [2*j + i] : désigne le (2*j + i )+1ème réel du tableau vect,
mat [i , j] : désigne le réel de la matrice mat en i+1ème ligne et j+1ème colonne.
La
taille
du
tableau
fixée
lors
de
sa
déclaration
est
sa
taille
maximum.
La
taille
effectivement
utilisée
pour
le
tableau
peut
varier
au
cours
de
l’algorithme.
Il
n’y
a
pas
de
mécanisme
de
mémorisation
automatique
de
la
taille
effective
du
tableau.
C’est
au
concepteur
de
l’algorithme
de
mettre
en
place
ce
mécanisme.
II.2.
EN
LANGAGE
C
Les
tableaux
se
déclarent
dans
les
zones
habituelles
de
déclarations
des
variables.
On
déclare
ainsi
un
tableau
à
N
dimensions.
On
réserve
alors
un
espace
suffisamment
grand
pour
que
le
tableau
nom_tableau
puisse
contenir
au
maximum
taille1 x taille2 x … x tailleN
(tailles
de
déclaration)
éléments
de
type
type.
L’élément
nom[0][0]…[0]
contient
la
première
valeur
de
type
type
du
tableau,
l’élément
nom[0][0]…[0][1]
contient
la
deuxième
valeur
de
type
type
et
l’élément
nom[taille1 - 1][taille2 - 1]…[tailleN - 1]
contient
la
dernière
valeur
de
type
type
;
à
condition
que
ces
valeurs
aient
été
affectées.
III.1.
EN
ALGORITHMIQUE
Pour
un
tableau
à
une
dimension
on
a
alors
la
syntaxe
suivante
:
type nom_tableau [taille] ← {valeur0, valeur1, …, valeurk}
Si k < taille-1 les valeurs manquantes d'un tableau d'entiers ou de réels prennent la valeur 0.
On
peut
aussi
omettre
la
taille
dans
une
déclaration
avec
initialisation
la
syntaxe
est
alors
:
type nom_tableau[ ] ← {valeur0, valeur1, …, valeurk}
La taille du tableau est alors k+1.
III.2. EN LANGAGE C
classe[i]
désigne le contenu de la case i+1 du tableau classe, variable de type eleve ;
classe[i].nom
désigne le contenu du champ nom de la variable classe[i], c’est une chaîne ;
classe[i].naissance
désigne
le
contenu
du
champ
naissance
de
la
variable
classe[i],
de
type
date
;
classe[i].naissance.jour
désigne le contenu du champ jour de la variable structurée classe[i], entier ;
classe[i].classement
désigne le contenu du champ classement de la variable classe[i], c’est un entier ;
IV.
REMARQUES
Les
indices
doivent
avoir
une
valeur
entière
positive
ou
nulle.
Les
indices
peuvent
donc
être
des
variables
entières
ou
encore
des
valeurs
entières
figées.
Les
tableaux
sont
généralement
manipulés
à
l’aide
d’instructions
de
contrôle
itératives
(en
structure
algorithmique
:
"pour",
"tant
que",
"faire…
tant
que"
;
en
C
:
boucles
for,
while
ou
do…while).
La
taille
(ou
les
tailles)
de
déclaration
du
tableau
doi(ven)t
être
connue(s)
au
moment
où
le
programme
réserve
la
place
pour
stocker
les
valeurs
du
tableau.
Ceci
nécessite
donc
l’utilisation
de
valeur(s)
fixe(s)
ou
de
constante(s).
EN
AUCUN
CAS
LA
TAILLE
DE
DECLARATION
NE
PEUT
ETRE
UNE
VARIABLE.
On
ne
peut
pas
avec
la
méthode
de
déclaration
présentée
ici
saisir,
par
exemple,
au
clavier
la
ou
les
tailles
du
tableau.
Le
programmeur
doit
donc
prévoir
des
tableaux
suffisamment
grands
pour
traiter
tous
les
cas.
Ceci
implique
que
l'utilisateur
n'utilise
pas
forcément
toutes
les
cases
du
tableau.
ON
MANIPULE
ALORS
UNE
VARIABLE
ENTIERE
CORRESPONDANT
A
LA
TAILLE
EFFECTIVE
DU
TABLEAU.
Les
éléments
d’un
tableau
sont
rangés
en
mémoire
suivant
l’ordre
obtenu
en
faisant
varier
le
dernier
indice
en
premier.
Les
éléments
d'un
tableau
sont
stockés
dans
des
cases
mémoires
contiguës
et
donc
un
tableau
est
entièrement
déterminé
par
l'adresse
de
son
premier
élément
;
l’élément
suivant
est
stocké
dans
la
zone
mémoire
qui
suit
et
ainsi
de
suite.
On
accède
à
deux
éléments
consécutifs
en
incrémentant
l’indice
désignant
le
premier.
L’élément
consécutif
à
celui
d’indice
k
est
celui
d’indice
k+1.
L'espace
mémoire
parcouru
en
passant
de
l’indice
k
à
l’indice
k+1
correspond
à
l'espace
mémoire
nécessaire
au
stockage
d'un
élément
du
tableau
et
donc
à
celui
du
type
type.
En
C,
la
valeur
des
indices
utilisés
n'est
pas
vérifiée.
La
zone
mémoire
pouvant
être
désignée
par
un
indice
trop
grand
n'est
pas
réservée,
la
valeur
se
trouvant
dans
cette
zone
peut
tout
à
fait
appartenir
à
un
autre
programme
de
l'ordinateur,
être
aberrante
ou,
dans
le
cas
des
tableaux
multidimensionnels,
correspondre
à
une
case
ayant
d'autres
valeurs
d'indices.
Les
indices
négatifs
peuvent
aussi
provoquer
des
erreurs.
Si
on
néglige
l’élément
d'indice
0
et
qu'on
déclare
un
tableau
de
taille
n+1
alors
on
retrouve
la
notation
matricielle
traditionnelle
où
les
indices
varient
de
1
à
n.
ATTENTION
!
ON
NE
PEUT
PAS
AFFECTER
DIRECTEMENT
LES
VALEURS
D'UN
TABLEAU
DANS
UN
AUTRE
TABLEAU
MEME
SI
CELUI-‐CI
A
LES
MEMES
TYPE,
DIMENSIONS
ET
TAILLES.
Le
nom
du
tableau
représente
l'adresse
en
mémoire
du
tableau
ainsi
que
celle
du
premier
élément
de
ce
même
tableau.
V. EXEMPLES
V.1.1.
Calcul
de
la
somme
des
valeurs
d’un
tableau
à
1
dimension
début
Variables
N=70
Entier a [N], i, n, s #include <iostream>
using namespace std ;
Afficher "Donnez la taille du tableau" #define N 70
Saisir n
main()
i←0
{
int a[N], i , n , s;
Saisir n et
non tous les
i <n? éléments // Saisie de la taille effective du tableau
oui de a cout << "Donner la taille utilisée : " ;
Afficher "Donnez les valeurs du tableau" cin >> n ;
Saisir a [ i ] // Saisie des éléments du tableau
for ( i = 0 ; i < n; i++)
i←i+1 {
cout<<"Entrer la valeur d’indice "<<i<<" : " ;
cin >> a[i] ;
s←0
}
// Initialisation de la somme
i←0 s = 0 ;
// Calcul de la somme
non for ( i = 0; i < n; i++ )
i <n? s += a[i] ;
oui cout << "Somme = " << s << endl ;
s←s+a[i] }
i←i+1
fin
début
Algorithme
donné
Figure
4.
Variables #include <iostream>
N = 50 using namespace std ;
Entier a [N], i, n, s, c #define N 50
c←0
i←0
non
i <n?
oui Compter les
non valeurs
a[i]<0?
négatives
oui
c ←c+1
i←i+1
fin
V.2.1. Calcul de la somme des valeurs d’un tableau de dimension 2
début
Variables
NL=30, N=40
Entier a [NL,NC], i, j, nc, nl, s
non main()
i < nl ? {
Saisir nl, float a[NL][NC], s ;
oui nc et tous int nc, nl, i, j ;
j←0 les
éléments // Saisie de la taille effective du tableau
de a cout << "Nombre de lignes du tableau : " ;
non cin >> nl ;
j < nc ?
cout << "Nombre de colonnes du tableau : " ;
oui cin >> nc ;
Afficher "Donnez les valeurs du tableau"
Saisir a [ i , j ] // Saisie des valeurs du tableau
for ( i = 0 ; i < nl; i++ )
for ( j = 0 ; j < nc ; j++ )
j←j+1 {
cout << "Entrer la valeur d’indice " ;
cout << i << " , " << j << " : " ;
i←i+1 cin >> a[i][j];
}
non
j < nc ?
oui
s←s+a[i,j]
j←j+1
i←i+1
fin
VI. EXERCICE
fin
VI.10.
EXERCICE
(RECHERCHE
DANS
UN
TABLEAU
DE
CHAINES
DE
CARACTERES)
Ecrire
un
programme
(algorithme
et
traduction
en
C)
permettant
d’effectuer
successivement
les
actions
suivantes
:
Entrer
n
mots
dans
un
tableau
T
avec
n<10.
Afficher
n
et
les
n
valeurs
du
tableau
T.
Entrer
un
mot
et
afficher
si
ce
mot
est
dans
le
tableau
ou
afficher
‘mot
inconnu’
sinon.
Indiquez
:
A
quoi
sert
la
boucle
while,
et
du
coup
que
faut-‐il
préciser
à
l’utilisateur
sur
la
marche
à
suivre
dans
le
premier
affichage
cout.
Quelle
valeur
doit
être
affectée
à
n
à
votre
avis,
et
à
quoi
correspond
cette
variable.
Que
calcule
et
affiche
la
deuxième
boucle
Pour,
en
particulier
à
quoi
correspond
cette
fois-‐ci
le
caractère
c.
#include <iostream>
using namespace std ; n = … ;
#define N 50 NbI = 0 ;
struct Ind NbM = 0 ;
{ string Nom ; //Nom de l’individu NbAn = 0 ;
char Car ; //Sexe : M ou F cout << c ;
int Nb ; //Nombre d’animaux domestiques for ( i=0 ; i<n ; i++ )
}; {
main() if ( Gens[i].Nom[1] == c )
{ Ind Gens[N] ; {
int i, n, NbI, NbM, NbAn ; NbI = NbI+1 ;
char c ; if ( Gens[i].Car == 'M' )
cout << " … " ; NbM += 1 ;
i = 0 ; NbAn += Gens[i].Nb ;
cin >> c ; }
do }
{ Gens[i].Car = 'c' ; cout << NbM/NbI ;
cin >> Gens[i].Nom ; cout << NbAn/NbI ;
cin >> Gens[i].Nb ; }
i = i+1 ;
cin >> c ;
} while ((c == 'M')||(c == 'F'));
Indiquer
:
Il
y
a
une
erreur
dans
les
déclarations,
laquelle
?
Qu’obtient-‐on
avec
les
valeurs
suivantes
saisies
au
clavier
?
4, "Biarritz", 5, 19, "Calvisano", 0, -67, "Cardiff", 10, 49, "Gloucester", 5, -1)
Que
réalise
cet
algorithme
?
#include <iostream>
#include <string>
using namespace std ;
#define N 16
struct Equipe
{
string Nom ; // Nom de l’équipe
int Pts ; // Nombre de points en championnat
int Diff ; // Différence cumulée
};
main()
{ Equipe T[N] ;
int i, n, Aux ;
cin >> n ;
for ( i=0 ; i < n ;i++)
cin >> T[i].Nom >> T[i].Pts >> T[i].Diff ;
for ( i=0 ; i < n-1 ;i++)
{ for ( j=i+1 ; j < n ;j++)
{
if ( (T[i].Pts < T[j].Pts) || ( (T[i].Pts==T[j].Pts)&&(T[i].Diff < T[j].Diff) ) )
{ Aux = T[i] ;
T[i] = T[j] ;
T[j] = Aux ;
} // if ( (T[i].Pts <
} // for ( j
} // for ( i
for ( i=0 ; i < n ;i++)
cout << T[i].Nom << " " << T[i].Pts << " " << T[i].Diff << endl ;
}
VI.16.
EXERCICE
On
considère
que
les
100
places
d'un
avion
sont
représentées
par
un
tableau
de
nombres
où
les
20
premières
places
sont
en
classe
affaire,
les
20
suivantes
de
première
classe
et
les
60
restantes
en
classe
économique.
La
valeur
0
d'une
case
signifie
que
la
place
est
libre
et
une
autre
valeur
signifie
qu'elle
est
réservée.
Ecrire
le
programme
(algorithme
et
traduction
en
C)
en
C
qui
doit
:
mettre
les
valeurs
du
tableau
à
0,
permettre
à
l'utilisateur
de
réserver
ou
libérer
des
places
en
fonction
de
la
classe
et
du
numéro
de
la
place
et
ceci
tant
qu'il
le
souhaite,
pour
cela
il
doit
disposer
de
la
liste
des
places
libres
de
la
classe
en
question.
Modifier cet algorithme pour que l’on puisse demander plusieurs fois le prix sans nouvelle saisie du tableau.
Modifier cet algorithme pour que l’on puisse en plus afficher le code des articles de ce prix.
Ecrire
un
algorithme
puis
le
programme
C
correspondant
qui
permet
la
saisie
des
valeurs
de
x1,
y1,
x2
et
y2,
qui
calcule
puis
affiche
pour
l'utilisateur
la
distance
entre
les
deux
points.
On
considère
maintenant
que
les
valeurs
des
coordonnées
des
deux
points
sont
contenues
dans
un
tableau
nommé
T
à
4
valeurs
réelles.
Ré
écrire
l'algorithme
de
la
question
1
et
le
programme
C
correspondant
en
tenant
compte
de
ce
changement.
Le
tableau
T
contient
désormais
un
nombre
de
points
quelconque
nommé
np
(au
moins
2
et
au
plus
50),
ce
nombre
étant
choisi
par
l'utilisateur.
Le
tableau
T
a
donc
la
forme
suivante
:
x1 y1 x2 y2 x3 y3 ... ... xnp ynp
On
peut
considérer
que
ce
tableau
T
représente
un
polygone
à
np
sommets.
Écrire
un
algorithme
puis
le
programme
C
correspondant
qui
permet
de
saisir
les
valeurs
du
tableau
T
puis
de
calculer
le
périmètre
du
polygone
ainsi
représenté.
Le
périmètre
du
polygone
est
la
somme
des
distances
entre
deux
points
consécutifs
du
tableau.
Attention,
il
faudra
prendre
en
compte
également
la
distance
entre
le
premier
point
et
le
dernier
point.
Soit
le
tableau
T
de
la
question
3
et
un
point
A
décrit
par
ses
deux
coordonnées
réelles
x
et
y.
Écrire
un
algorithme
puis
le
programme
C
correspondant
qui,
après
avoir
saisi
les
valeur
du
tableau
et
des
coordonnées
de
A,
sélectionne
dans
T
les
points
dont
la
distance
au
point
A
est
inférieure
ou
égale
à
une
valeur
fixée
par
l'utilisateur.
Les
points
sélectionnés
seront
stockés
dans
un
tableau
T2
dont
le
format
est
similaire
à
celui
de
T.
Ecrire
un
algorithme
puis
un
programme
en
langage
C
qui
permet
de
:
Saisir
un
ensemble
de
revues,
Calculer
puis
stocker
dans
le
deuxième
tableau
le
coût
de
ces
revues,
Afficher
chaque
revue
et
le
coût
de
son
abonnement.
Le
coût
total
des
abonnements,
L'abonnement
le
moins
et
le
plus
cher,
Ecrire
un
algorithme
qui
permet
de
saisir
le
stock
du
magasin,
de
l'afficher
puis
d'afficher
la
liste
des
articles
devant
être
réapprovisionnés.
Modifiez
l’algorithme
puis
le
programme
en
langage
C
pour
qu’il
crée
un
deuxième
polygone,
translaté
d’un
premier
polygone
selon
un
point.
Le
premier
polygone
et
le
point
devront
être
saisis
puis
affichés,
le
second
polygone
doit
être
calculé
puis
affiche.
Modifiez
l’algorithme
puis
le
programme
en
langage
C
pour
qu’il
crée
un
troisième
polygone
en
appliquant
à
un
premier
polygone
une
homothétie
de
centre
O
et
de
rapport
un
réel.
Modifiez
l’algorithme
puis
le
programme
en
langage
C
pour
qu’il
crée
un
quatrième
polygone
en
appliquant
à
un
premier
polygone
une
homothétie
de
centre
un
point
et
de
rapport
un
réel.
Modifiez
l’algorithme
puis
le
programme
en
langage
C
pour
qu’il
crée
un
cinquième
polygone
par
symétrie
centrale
d'un
premier
polygone
par
rapport
à
un
point.
Rappels
:
Le
translaté
d’un
point
M(a,
b)
par
rapport
au
point
p(x,
y)
est
le
point
M’(a’=x+a,
b’=y+b).
L’homothétique
de
centre
O
d’un
point
M(a,
b)
est
le
point
M’(a’=ka,
b’=kb).
Une
homothétie
de
centre
C(x,
y)
et
de
rapport
k
appliquée
à
un
point
M(a,
b)
donne
le
point
M’(a’,
b’)
tel
que
a’
–
x
=
k
(a
-‐
x)
et
b’
–
y
=
k
(b
–
y).
Le
symétrique
d’un
point
M(a,b)
par
rapport
au
point
p(x,y)
est
le
point
M’(a’=2x-‐a,
b’=2y-‐b).
Une
symétrie
centrale
est
une
homothétie
de
rapport
-‐1.
MODULARITE
I.
GENERALITE
L’objet
de
la
modularité
en
informatique
est
de
considérer
un
problème
complexe
en
un
arrangement
de
problèmes
plus
simples
qui
peuvent
être
également
considérés
en
arrangement
de
problèmes
encore
plus
simples
et
ainsi
de
suite.
Les
sous-‐
problèmes
sont
alors
rédigés
sous
la
forme
de
«
morceaux
»
de
programme
ou
d’algorithme
appelés
modules,
routines
ou
encore
sous-‐programmes.
Généralement,
le
recours
à
la
notion
de
modularité
est
la
seule
manière
raisonnable
de
traiter
un
problème
complexe
en
le
décomposant
en
arrangements
successifs
de
problèmes
plus
simples.
I.1.
INTERETS
La
rédaction
de
modules
est
utile
si
les
opérations
qu'ils
effectuent
sont
appelées
souvent
pour
des
paramètres
de
valeurs
différentes.
Elle
est
encore
utile
si
elle
constitue
une
étape
logique
dans
la
décomposition
hiérarchique
en
sous
problèmes
plus
simples
du
problème
complexe
posé
au
programmeur
(ou
groupe
de
programmeurs)
dans
le
cahier
des
charges
du
programme.
La
modularité
permet
en
cas
d'utilisation
répétitive
d'un
ensemble
d'actions
en
différents
points
d'un
programme
ou
par
différents
programmes
d’économiser
de
la
mémoire
(code
présent
une
seule
fois)
et
permet
assez
souvent
une
meilleure
lisibilité
qui
conduit
notamment
à
faciliter
le
débogage.
I.2.
BIBLIOTHEQUES
Les
modules
rédigés
sous
la
forme
de
«
morceaux
»
de
programme
présentant
un
caractère
suffisamment
générique
sont
souvent
rassemblés
dans
des
bibliothèques
dans
le
but
d’être
réutilisés
par
d’autres
programmes.
Une
bibliothèque
contient
donc
plusieurs
modules
traitant
généralement
d’une
même
famille
de
problèmes
comme
:
• les
fonctions
mathématiques,
• la
manipulation
de
chaînes
de
caractères,
• la
communication
avec
l’utilisateur
(entre
le
programme,
le
clavier
et
l’écran…),
• …
De
nombreuses
bibliothèques
sont
généralement
jointes
aux
différents
IDE
(Integrated
Development
Environment
–
Environnement
de
Développement
Intégré)
comme
Code::Blocks,
Visual
C++,
Borland
C++
Builder,
Eclipse…
Les
programmeurs
ont
également
la
possibilité
de
créer
leurs
propres
bibliothèques
de
modules
qu’ils
ont
déjà
développés
toujours
dans
le
but
de
pouvoir
réutiliser
ces
modules
dans
d’autres
programmes.
Un appel à une procédure peut être considéré comme une instruction comme cela est montré dans la case violette de la
p
our
le
module
TrideTableau.
Un
appel
à
fonction
peut
être
effectué
dans
une
expression,
il
se
substitue
alors
à
n’importe
qu’elle
valeur
du
type
produit
par
cette
fonction,
comme
cela
est
montré
dans
la
case
violette
de
la
Figure
6
pour
le
module
MoyenneTableau.
Par
convention,
les
noms
des
modules
appelés
lors
de
l’appel
sont
suivis
de
la
liste
des
paramètres
placés
entre
parenthèses.
Un
module
peut
ne
pas
avoir
de
paramètre,
comme
cela
est
le
cas
en
C
et
C++
de
la
fonction
rand(),
dans
ce
cas
le
nom
du
module
sera
tout
de
même
suivi
des
deux
parenthèses.
début
Variables Internes
Réel tabreel [20] ...
Entier tabsize, k main()
{
float tabreel [20]
;
Afficher " Entrez le nombre de valeurs (<=20) : " int tabsize, k
;
Saisir tabsize cout<<"Entrez le nombre de valeurs" ;
cout << " (<=20) :";
cin>>tabsize
;
k!0 for (k=0
; k<tabsize
;k++)
{
cout<<"valeur numero " <<k<<"
: "
;
non
k < tabsize ? cin>>tabreel[k]
;
}
oui
TriDeTableau(tabreel, tabsize);
Afficher "valeur numéro ", k+1 ...
Saisir tabreel[k]
}
k ! k+1
TriDeTableau ( tabreel , tabsize)
fin
début
Variables Internes
Réel tabreel [20], moy
Entier tabsize, k ...
main()
{
Afficher " Entrez le nombre de valeurs (<=20) : " float tabreel [20]
; moy
Saisir tabsize
int tabsize, k
;
cout<<"Entrez le nombre de valeurs" ;
k!0 cout << " (<=20):";
cin>>tabsize
;
for (k=0
; k<tabsize
;k++)
non
k < tabsize ? {
oui
cout<<"valeur numero " <<k<<"
: "
;
cin>>tabreel[k]
;
Afficher " valeur numéro ", k+1
Saisir tabreel[k] }
moy = 3*MoyenneTableau(tabreel, tabsize)/4;
cout<<"le 3/4 de la moyenne des"
;
k ! k+1 cout <<"valeurs est " <<moy
;
...
}
5. Le
module
appelé
place
les
valeurs
des
paramètres
qu’il
doit
modifier
dans
les
variables
du
module
appelant
correspondantes
et,
si
le
module
appelé
est
une
fonction,
il
transfère
la
valeur
qu’il
a
calculée
au
module
appelant.
6. L’exécution
du
module
appelant
reprend
avec
les
valeurs
des
variables
placées
en
paramètres
éventuellement
modifiées
et,
si
le
module
appelé
est
une
fonction,
le
module
appelant
exploite
la
valeur
calculée
par
le
module
appelé
(l’affecte
dans
une
variable,
évalue
l’expression
dans
laquelle
elle
figure,
l’affiche…).
Module'Appelant' Module'Appelé'
temps'
1' 2'
3'
5' 4'
6'
Figure
7
:
Schéma
de
principe
de
communication
entre
modules.
Lors
d’un
appel
à
un
module
les
paramètres
apparaissant
entre
les
parenthèses
sont
appelés
paramètres
effectifs
parce
qu’il
s’agit
des
paramètres
à
partir
desquels
un
module
effectue
ses
actions.
Le
principe
de
communication
montre
que,
lors
de
l’étape
2,
le
module
appelé
reçoit
des
valeurs
du
module
appelant.
Ces
valeurs
transmises
sont
appelées
paramètres
effectifs
d’entrée.
Lors
de
l’étape
5,
le
module
appelé
modifie,
le
cas
échéant,
les
valeurs
de
certaines
variables
du
module
appelant
placées
dans
la
liste
de
paramètres.
Ces
paramètres
sont
appelés
paramètres
effectifs
de
sortie.
Certains
paramètres
effectifs
peuvent
être
à
la
fois
des
paramètres
d’entrée
et
des
paramètres
de
sortie.
Il
s’agit
alors
de
paramètres
effectifs
d’entrée-‐sortie.
C’est
le
cas
dans
l’exemple
de
la
Figure
5
où
le
module
TriDeTableau
utilise
la
valeur
du
tableau
de
réel
Tabreel
afin
de
le
modifier
en
un
tableau
de
réel
trié.
Concernant
les
paramètres
effectifs
de
sortie
ou
d’entrée-‐sortie,
lors
de
l’étape
5,
le
module
appelé
«
cherche
»
une
zone
mémoire
pour
stocker
la
nouvelle
valeur
du
paramètre
qui
ne
peut
donc
être
qu’une
variable
(ou
une
case
d’un
tableau
de
même
type).
Donc
lors
de
l’appel
d’un
module,
les
paramètres
effectifs
de
sortie
ou
d’entrée-‐sortie
ne
peuvent
être
que
des
variables
du
module
appelant.
Par
contre,
les
paramètres
effectifs
d’entrée
peuvent
être
des
valeurs,
des
constantes,
des
expressions
ou
des
variables
correspondant
au
type
de
valeur
attendu.
Pour
bien
utiliser
un
module
il
faut
:
1. connaître
son
nom,
2. savoir
ce
qu’il
fait
dans
les
grandes
lignes,
3. connaître
la
liste
des
paramètres
et
leur
type,
4. savoir
s’il
s’agit
de
paramètres
d’entrée,
de
sortie
ou
d’entrée-‐sortie,
5. savoir
à
quoi
correspondent
ces
paramètres
pour
la
tâche
réalisée
par
le
module.
Ces
savoirs
sont
accessibles
à
l’aide
des
documentations
associées
à
l’IDE
s’il
s’agit
de
modules
appartenant
aux
bibliothèques
fournies
avec
l’IDE,
ou
encore
grâce
aux
commentaires
associés
aux
algorithmes
ou
inclus
dans
les
programmes
pour
tout
autre
module.
III.2.
EN-‐TETE
L'en-‐tête
d'un
module
est
primordial
dans
le
sens
où
celui-‐ci
définit
une
sorte
d'interface
de
communication
entre
le
module
appelant
et
le
module
appelé.
Cette
«
interface
»
est
constituée
de
plusieurs
éléments
:
un
nom
pour
appeler
le
bon
module,
une
liste
des
paramètres
formels
avec
pour
chacun
de
ces
paramètres
:
o son
nom
(ce
nom
est
celui
avec
lequel
les
actions
du
module
sont
décrites
dans
le
corps
de
celui-‐ci),
o son
type
c'est-‐à-‐dire
l'ensemble
de
valeurs
que
ce
paramètre
admet
(réel,
booléen,
entier,
chaîne
de
caractères,
une
structure
particulière…),
o son
genre
(paramètre
d'entrée,
paramètre
de
sortie,
paramètre
d'entrée-‐sortie),
s'il
s'agit
d'une
fonction,
le
type
de
la
valeur
produite
par
le
module
(réel,
booléen,
entier,
chaîne
de
caractères,
structure
particulière…)
appelé
aussi
type
de
retour.
III.2.2. En C++
III.2.2.1. Syntaxe
En
C++
la
syntaxe
de
l'en-‐tête
d'un
module
est
le
suivant
:
TypeDeRetour NomDuModule (liste des paramètres)
Où
:
NomDuModule est le nom du module,
TypeDeRetour est
- le type de la valeur produite par le module pour une fonction
- void pour une procédure.
La
liste
des
paramètres
comporte
le
type,
le
nom
et
le
genre
des
paramètres
formels
:
Pour un paramètre formel d'entrée :
typeduparametre nomduparametre
Pour un paramètre formel de sortie ou d'entrée-sortie :
typeduparametre & nomduparametre
ou typeduparametre& nomduparametre
ou typeduparametre &nomduparametre
Les paramètres sont séparés par une virgule.
Exemples
:
void permuter (float& x, float& y) // permutation du contenu de 2 variables
int maximum (int a, int b) // calcul du maximum de 2 entiers
En
C++,
il
n'y
a
pas
de
différence
entre
paramètre
d'entrée-‐sortie
et
paramètre
de
sortie.
variables
représentant
ces
paramètres
de
sortie
effectifs
reçoivent
les
valeurs
des
paramètres
formels
du
module
appelé
qui
a
dû
leur
donner
une
valeur.
On
parle
alors
de
passage
par
référence.
Lors
de
l'appel
d'un
module
les
valeurs
des
paramètres
formels
d'entrée-‐sortie
du
module
appelé
reçoivent
les
valeurs
des
paramètres
effectifs
d'entrée-‐sortie
correspondant.
En
fin
d’exécution,
les
variables
représentant
ces
paramètres
d'entrée-‐
sortie
effectifs
reçoivent
les
valeurs
des
paramètres
formels
du
module
appelé
(qui
a
pu
modifier
les
valeurs).
On
parle
toujours
de
passage
par
référence.
En
C++,
dans
le
cas
des
paramètres
d'entrée-‐sortie
ou
de
sortie
(puisqu'il
n'y
a
pas
de
distinction)
tout
ce
passe
comme
si
le
paramètre
effectif
du
module
appelant
était
substitué
au
paramètre
formel
du
module
appelé
(comme
si
le
module
appelé
opérait
directement
sur
le
paramètre
effectif).
III.3. CORPS
III.3.1.
Constitution
Le
corps
d'un
module
comporte
la
séquence
d'instructions
décrivant
les
actions
du
module.
Ces
instructions
peuvent
comporter
des
appels
à
d'autres
modules.
Cette
séquence
a
un
début
et
une
fin
et
donc,
en
C
et
C++,
elle
est
encadrée
par
"{"
et
"}".
Les
paramètres
formels
ne
sont
pas
déclarés
dans
la
partie
«
variables
locales
»
puisqu’ils
le
sont
dans
l’en-‐tête.
Pour
réaliser
ses
actions,
un
module
peut
avoir
besoin
de
variables
internes
propre
au
module,
qu'il
faut
définir
et
déclarer.
Cette
déclaration
est
effectuée
en
début
de
module.
Le
nom
des
variables
internes
et
des
paramètres
formels
d'un
module
sont
propres
au
module,
ils
n'existent
que
lors
de
l'exécution
de
celui-‐ci,
et
peuvent
donc
être
les
mêmes
noms
que
ceux
d'autres
variables
ou
paramètres
d'autres
modules.
III.4.
EXEMPLES
Nous
proposons
dans
ce
paragraphe
des
exemples
de
modules
définis
à
l'aide
d'un
logigramme
algorithmique
et
de
code
C++.
maximum&
int maximum (int a, int b)
Entier'a'
Entier'b' {
if (a < b)
Entier & return b ;
a'<'b?'
non & return a ;
}
oui &
Retour'
b & Retour'
a &
Figure
9
:
Fonction
Maximum.
permuter'
Réel%x%
Réel%y%
y%%!%tempo%
fin%
Figure
10
:
Procédure
permuter.
MoyenneTableau+
Réel%vect%[%]%%
Entier%lv% float MoyenneTableau (float vect[], int lv)
{
+
Réel int k ;
float s ;
Variables%internes%
%Entier%k%
%Réel%s% s = 0. ;
for (k=0 ; k<lv ; k++)
s += vect[k] ;
s%%!%0% return s/lv ;
}
k%!%0%
non%
k%<%lv%?%
oui%
s%!%s%+%vect%[k]%
k%!%k+1%
Retour%
s+/+lv +
Figure
11
:
Fonction
MoyenneTableau
TriDeTableau*
Réel#tab#[#]##
Entier#n#
Variables#internes#
#Entier#i ##
#Entier#max# ##
#Entier##fin ## void TriDeTableau (float tab[], int n)
{
int i, fin, max ;
fin# #n$1# for (fin=n-1 ; fin>=1 ; fin--)
for(i=0 ; i<fin-1 ; i++)
if (tab[i]>tab[i+1])
fin##≥#1#?#
{
oui# max = tab[i+1] ;
tab[i+1] = tab[i] ;
i# #0#
tab[i] = max ;
non# }
i#<#fin$1#?# }
oui#
non#
tab[i]#>#tab[i+1]#
oui#
max# #tab[i+1]#
tab[i+1] #tab[i]#
tab[i] #max#
i# #i+1#
fin# #fin$1#
Fin#
Figure
12
:
Procédure
TriDeTableau.
#include <iostream>
using namesace std;
#include "mybib.h"
#define PI 3.1416
struct elt
{
int entier ;
float val ;
} ;
const unsigned int k=3 ;
main ()
{
char alpha, beta ;
float x, y, z ;
/* Commentaire */
}
Figure
13
:
Trame
d’organisation
d’un
programme
avec
fonctions
en
C.
Toutefois,
les
modules
ne
peuvent
pas
être
déclarés
dans
n'importe
quel
ordre.
L'ordre
est
basé
sur
le
fait
qu'on
ne
peut
utiliser
que
ce
qui
a
été
préalablement
déclaré.
Ainsi,
en
considérant
la
situation
suivante
où
un
module
ModZ
appelle
un
module
ModY
qui
lui-‐même
appelle
un
module
ModX
et
un
module
ModW.
Il
faudra
d'abord
déclarer
les
modules
ModW
et
ModX
(dans
l'ordre
de
son
choix),
puis
le
module
ModY
et
enfin
le
module
ModZ.
Ceci
explique
pourquoi
la
fonction
principale
main()est
déclarée
à
la
fin.
Une
alternative
est
la
déclaration
des
prototypes
(dans
l'ordre
de
son
choix)
puis
des
modules
avec
leur
en-‐tête
(dans
l'ordre
de
son
choix
aussi).
Un
prototype
est
l'en-‐tête
d'une
fonction
suivi
d'un
";".
Il
permet
de
définir
la
forme
de
la
fonction
avant
sa
définition.
Il
ne
dispense
pas
de
définir
la
fonction,
et
lors
de
cette
définition
l’en-‐tête
doit
être
présent
et
doit
correspondre
exactement
au
prototype.
Exemples
pour
les
modules
suivants
:
int maximum (int a, int b);
void permuter (float& x, float& y);
float MoyenneTableau (float vect[], int lv);
void TriDeTableau (float tab[], int n);
ou
encore
en
les
débarrassant
des
noms
des
paramètres
formels
:
int maximum (int, int);
void permuter (float& , float&);
float MoyenneTableau (float *, int);
void TriDeTableau (float *, int);
Dans
le
cas
des
paramètres
formels
qui
sont
des
tableaux,
il
doit
subsister
autant
de
"*"
que
le
tableau
compte
de
dimensions.
IV. EXERCICES
IV.1.
EXERCICE
1
On
déclare
un
module
de
la
manière
suivante
:
Fct1
Réel x
Booléen y
Réel
non
x=0?
oui
y ← vrai
y ← faux
non
x>0?
Retour oui
0
Retour
1/x
Retour
1 / ( – x)
A
quoi
sert
le
paramètre
y
?
Que
fait
le
module
Fct1
?
Lors
d'un
appel
à
la
fonction
Fct1,
combien
de
fois,
au
maximum,
l'instruction
Retour
peut-‐elle
être
exécutée
?
Peut-‐on
écrire
dans
un
algorithme
les
instructions
suivantes
comprenant
un
appel
à
la
fonction
Fct1
?
y
ß
Fct1(2,a),
où
y
est
une
variable
de
type
Booléen
et
a
est
une
variable
de
type
Booléen
x
ß
Fct1(x,a),
où
x
est
une
variable
de
type
Réel
et
a
est
une
variable
de
type
Booléen
y
ß
Fct1(x,vrai),
où
x
et
y
sont
des
variables
de
type
Réel
a
ß
(3
+
Fct1(b,c))/2,
où
a
et
b
sont
des
variables
de
type
Réel
et
c
une
variable
de
type
Booléen
a
ß
Fct1(a+b+3,c)/2,
où
a
et
b
sont
des
variables
de
type
Réel
et
c
une
variable
de
type
Booléen
IV.2.
EXERCICE
2
Ecrire
une
fonction
permettant
la
saisie
d'une
matrice.
Ecrire une fonction retournant la trace d'une matrice si elle est carrée.
Ecrire
une
fonction
calculant
la
somme
de
deux
matrices,
stockant
le
résultat
dans
une
troisième
matrice
et
retournant
0,
si
le
calcul
n'est
pas
possible.
Ecrire
une
fonction
calculant
le
produit
de
deux
matrices,
stockant
le
résultat
dans
une
troisième
matrice
et
retournant
0,
si
le
calcul
n'est
pas
possible.
Ecrire
un
programme
permettant
d'effectuer
des
opérations
sur
des
matrices
où
l'utilisateur
peut
saisir,
resaisir,
faire
les
opérations
souhaitées,
jusqu'à
ce
qu'il
veuille
quitter
le
programme.
IV.3.
EXERCICE
3
On
déclare
un
module
de
la
manière
suivante
:
Fct1
Réel A
Entier n
Réel B
Booléen
Variables Internes
entier j
non
n=0?
oui non
n>0?
B←1 oui
B←0
B←0
Retour Retour
vrai j!1 faux
non
j≤n?
oui
B←B+A
Retour
vrai
A
quoi
sert
le
paramètre
retourné
?
Que
fait
le
module
Fct1
?
Lors
d'un
appel
à
la
fonction
Fct1,
combien
de
fois
au
maximum,
l'instruction
Retour
peut-‐elle
être
exécutée
?
Peut-‐on
écrire
dans
un
algorithme
les
instructions
suivantes
comprenant
un
appel
à
la
fonction
Fct1
?
y
ß
Fct1(2,5,a),
où
y
est
une
variable
de
type
Booléen
et
a
est
une
variable
de
type
Booléen
a
ß
Fct1(x,k,x),
où
x
est
une
variable
de
type
Réel,
k
est
une
variable
de
type
entier
et
a
est
une
variable
de
type
Booléen
a
ß
Fct1(x,3,5.5),
où
a
est
une
variable
de
type
Booléen,
x
est
une
variable
de
type
Réel
c
ß
Fct1(b,3+n,a),
où
a
et
b
sont
des
variables
de
type
Réel,
n
une
variable
de
type
entier
et
c
une
variable
de
type
Booléen
c
ß
Fct1(a+3,-‐5,b)/2,
où
a
et
b
sont
des
variables
de
type
Réel
et
c
une
variable
de
type
Booléen
IV.4.
EXERCICE
4
Ecrire
une
fonction
permettant
de
trier
par
ordre
croissant
le
contenu
de
2
variables
entières
a
et
b,
et
respectant
l’en-‐tête
suivant
:
void tri2(int & a, int & b)
Ecrire
une
fonction
permettant
de
trier
par
ordre
croissant
le
contenu
de
3
variables
entières
a,
b
et
c,
et
respectant
l’en-‐tête
suivant
:
void tri3(int & a, int & b, int & c)
Utiliser
ces
fonctions
pour
écrire
un
programme
permettant
de
rentrer
les
dimensions
a1,
b1,
c1
et
a2,
b2,
c2
de
2
boîtes
et
de
les
comparer
dimension
par
dimension
ou
globalement.
IV.5.
EXERCICE
5
On
suppose
que
l’on
dispose
de
deux
tableaux
d’entiers
ordonnés.
Réalisez
un
module
(algorithme
et
langage
C)
qui
supprime
les
éléments
identiques
d’un
tableau
dans
un
deuxième.
Tableau 1 3 3 4 5 7 8 10 10 41
Résultat 3 4 5 7 8 10 41
Exemple
d’application
de
l’algorithme
de
suppression
d’éléments
identiques
Réalisez
un
module
(algorithme
et
langage
C)
qui
crée
l’intersection
de
deux
tableaux
ne
possédant
pas
d’éléments
identiques.
Tableau 1 3 4 5 7 8 10 41
Tableau 2 3 6 8 41 50
Résultat 3 8 41
Exemple
d’application
de
l’algorithme
de
création
de
l’intersection
Réalisez
un
module
(algorithme
et
langage
C)
qui
crée
l’union
de
deux
tableaux
ne
possédant
pas
d’éléments
identiques.
Tableau 1 3 4 5 7 8 10 41
Tableau 2 3 6 8 41 50
Résultat 3 4 5 6 7 8 10 41 50
Exemple
d’application
de
l’algorithme
de
création
de
l’union
Réalisez
un
module
(algorithme
et
langage
C)
qui
crée
la
différence
entre
deux
tableaux
qui
ne
possèdent
pas
d’éléments
identiques
Tableau 1 3 4 5 7 8 10 41
Tableau 2 3 6 8 41 50
Différence entre 1 et 2 4 5 7 10
Différence entre 2 et 1 6 50
Exemple
d’application
de
l’algorithme
de
création
de
la
différence
Réalisez
un
module
(algorithme
et
langage
C)
qui
crée
la
différence
symétrique
entre
deux
tableaux
(union
des
différences
mutuelles
entre
les
deux
tableaux).
Tableau 1 3 4 5 7 8 10 41
Tableau 2 3 6 8 41 50
Résultat 4 5 6 7 10 50
Exemple
d’application
de
l’algorithme
de
création
de
la
différence
symétrique.
Réalisez
un
module
principal
en
langage
C
qui
effectue
la
saisie
de
deux
tableaux
d’entiers,
les
trie,
supprime
les
éléments
identiques,
affiche
les
résultats,
crée
l’union
des
deux
tableau,
l’affiche,
crée
l’intersection
des
deux
tableaux,
l’affiche,
crée
la
différence
entre
le
tableau
1
et
le
tableau
2,
l’affiche,
crée
la
différence
entre
le
tableau
2
et
le
tableau
1,
l’affiche,
crée
la
différence
symétrique
entre
deux
tableaux
et
l’affiche.
IV.6.
EXERCICE
6
Qu’affichera
le
programme
suivant
:
#include <iostream>
int fct1(int tab[ ] , int ltab, int v)
{ int i ;
i=0 ; main()
while ( i < ltab ) {
{ int letab[50]={ 1, 3, 5, 7, 9, 11 , 13, 15};
if (tab[i] == v) int ldeletab, a ;
return i ;
i++ ; cout << "Un : " << fct1(letab, 8, 18) ;
} cout << endl;
return (-1) ; cout << "Deux : " << fct1(letab, 8, 7);
} cout << endl;
void fct2(int t[ ] , int <, int p) ldeletab = 8 ;
{ if (fct1(t, lt, p) == -1) a = 18 ;
{ fct2(letab, ldeletab, a) ;
t[lt] = p ; cout << "Trois : " << "Avec " << a ;
lt++ ; cout << " on obtient : ";
} ecrire(letab, ldeletab) ;
} a=7 ;
void ecrire(int tab[ ], int ltab) fct2(letab, ldeletab, a) ;
{ int i ; cout << "Quatre : " << "Avec " << a ;
cout << " on obtient : ";
cout << tab[0] ; ecrire(letab, ldeletab) ;
for (i=1 ; i < ltab ; i++) }
cout << " , " << tab[i] ;
cout << endl ;
}
IV.7.
EXERCICE
7
Nous
considérons
le
type
structuré
animal
représentant
des
animaux
d’un
magasin.
Ces
animaux
possèdent
un
code
représenté
par
l’entier
num,
un
nom
les
désignant,
un
code
du
type
de
nourriture
mangée
par
cet
animal
et
représenté
par
l’entier
eat,
et
enfin,
un
poids
minimum
de
nourriture
à
lui
donner
par
jour
représenté
par
le
réel
pds,
ce
poids
est
exprimé
en
grammes.
Les
types
de
nourriture
sont
au
nombre
de
NbType
et
ont
pour
code
les
entiers
de
1
à
NbType.
Un
magasin
peut
contenir
au
maximum
250
animaux.
Type structuré animal
début
Entier num
Chaîne nom
Entier eat
Réel pds
fin
Ecrire
les
algorithmes
(au
moins
dans
les
grandes
lignes)
et
leur
traduction
en
C
:
1) Une
action
qui
saisit
les
caractéristiques
d’un
animal.
2) Une
action
qui
saisit
un
tableau
d’animaux
(elle
doit
appeler
l’action
1,
on
demande
le
nombre
d’animaux
à
l’utilisateur).
3) Une
action
qui
à
partir
du
code
du
type
de
nourriture
donné
en
paramètre
d’entrée,
calcule
le
poids
nécessaire
de
cette
nourriture
pour
les
animaux
du
magasin.
Cette
action
ne
doit
faire
ni
saisie
au
clavier
ni
affichage
à
l’écran.
4) Un
programme
principal
qui
:
Demande
à
l’utilisateur
la
valeur
du
nombre
de
type
de
nourriture
du
magasin
(valeur
de
NbType),
Saisit
un
tableau
d’animaux,
Affiche
le
poids
nécessaire
de
chaque
type
de
nourriture
pour
le
magasin
par
jour.
IV.8.
EXERCICE
8
Ecrire
une
fonction
retournant
1
si
un
nombre
entier
n
est
premier
et
0
sinon,
et
respectant
l’en-‐tête
suivant
:
int premier(int n)
Utiliser cette fonction pour écrire un programme permettant d’afficher les nombres premiers inférieurs à 100.
IV.9.
EXERCICE
9
Ecrire
une
fonction
permettant
la
saisie
d’un
vecteur
(tableau
à
une
dimension).
Ecrire
une
fonction
retournant
produit
scalaire
de
deux
vecteurs,
cette
fonction
doit
retourner
une
valeur
permettant
de
savoir
i
le
produit
scalaire
est
valide.
Ecrire une fonction calculant la norme d’un vecteur (on fera appel à la fonction écriteau 3).
Ecrire un programme permettant de saisir deux vecteurs, de calculer leur norme et leur produit scalaire.
Ecrire
les
algorithmes
(au
moins
dans
les
grandes
lignes)
et
leur
traduction
en
C
:
1) Une
action
qui
saisit
les
caractéristiques
d’un
article.
2) Une
action
qui
saisit
un
tableau
d’articles
(elle
doit
appeler
l’action
1,
on
demande
le
nombre
d’articles
à
l’utilisateur).
3) Une
action
qui
à
partir
du
code
du
fournisseur
donné
en
paramètre
d’entrée,
calcule
le
montant
du
stock
des
articles
de
ce
fournisseur
en
magasin.
Cette
action
ne
doit
faire
ni
saisie
au
clavier
ni
affichage
à
l’écran.
4) Un
programme
principal
qui
:
Demande
à
l’utilisateur
la
valeur
du
nombre
de
fourniseurs
du
magasin
(valeur
de
NbFournisseur),
Saisit
un
tableau
d’articles,
Affiche
le
montant
du
stock
pour
chaque
fournisseur.
Ecrire
une
fonction
ou
procédure
qui
à
partir
d’une
articulation
produit
la
valeur
0
si
l’articulation
est
dans
une
position
confortable,
1
si
elle
est
non
recommandée
et
100
si
elle
est
dangereuse.
Traduisez
là
en
C.
Ecrire
une
fonction
ou
procédure
qui
à
partir
d’un
tableau
représentant
un
mannequin,
produit
le
score
de
confort
de
la
position
du
mannequin.
Ce
score
est
obtenu
par
la
somme
de
la
valeur
de
chaque
articulation.
Cette
action
doit
faire
appel
à
l’action
écrite
au
1.
Traduisez
la
en
C.
Ecrire
une
fonction
C
qui
à
partir
d’un
polygone
et
d’un
nombre
entier
représentant
le
rang
maximum,
crée
le
tableau
des
nombres
polygonaux
lui
correspondant,
de
rang
1,
2,
3…,
rang
maximum.
On
utilise
la
formule
1
donnée
ci-‐dessus
pour
le
calcul.
Exemple
:
pour
un
polygone
à
4
côtés
(c’est-‐à-‐dire
un
carré),
et
pour
un
rang
maximum
de
6
on
obtient
le
tableau
contenant
6
valeurs
:
1
;
4
;
9
;
16
;
25
;
36.
On
dispose
(ne
pas
écrire
ces
actions)
:
• de
l’action
AffichTab
permettant
l’affichage
des
éléments
d’un
tableau
d’entiers,
void AffichTab ( int t[ ], int )
• et
de
l’action
Intersection
qui
produit
l’intersection
de
deux
tableaux,
c’est-‐à-‐dire
le
tableau
des
éléments
communs.
void Intersection (int t[ ], int , int u[ ], int , int r[ ], int & )
Ecrire une fonction C nommée SaisieLivraison permettant de saisir au clavier un bordereau de livraison.
Ecrire
une
fonction
C
nommée
ModifStockEnCours
qui,
à
partir
du
tableau
des
pièces
en
stock
et
d’une
livraison
modifie
le
stock
en
cours
(attention
ajout
ou
modification).
Ecrire
un
programme
principal
C,
qui
saisit
le
tableau
du
stock
en
cours,
puis
qui
modifie
ce
tableau
de
stock
au
fur
et
à
mesure
des
livraisons
arrivant,
et
enfin
affiche
le
contenu
du
tableau
de
stock.
Vous
ferez
appel
aux
actions
SaisieStockEnCours,
SaisieLivraison,
ModifStockEnCours
et
AffichStockEnCours.
Comment
pourrait-‐on
stocker
des
informations
sur
les
fournisseurs
des
pièces
(sachant
qu’un
type
de
pièce
peut
être
fourni
par
plusieurs
fournisseurs)
?
Pour
cela,
Proposez
un
nouveau
type
structuré
TPiece.
Remarque
:
Attention
au
passage
de
paramètres,
aucun
affichage
(écriture)
ou
saisie
(lecture)
ne
doit
être
fait
dans
l’action
ModifStockEnCours.
Exemple
:
On
commence
par
saisir
le
tableau
du
stock
suivant
(ici
le
nombre
de
pièces
de
code
différent
est
égal
à
4)
:
Ecrire
la
fonction
C
SaisieArt
permettant
la
saisie
d
‘un
seul
articles
d’un
magasin.
On
respectera
l’entête
:
TArt SaisieArt()
Ecrire
la
fonction
C
SaisieMag
permettant
la
saisie
des
articles
d’un
magasin,
et
leur
stockage
dans
le
tableau
Mag
de
taille
NbArt.
Il
faut
appeler
la
fonction
écrite
au
1).
On
respectera
l’entête
:
void
SaisieMag(TArt
Mag[ ], int & NbArt)
Ecrire
l’action
Peser
qui
indique
le
poids
en
kilos
d’une
quantité
d’un
article.
Cette
action
sert
à
simuler
l’utilisation
d’une
balance
pour
obtenir
le
poids
d’un
article.
Il
suffit
de
saisir
au
clavier
le
poids
;
On
respectera
l’entête
: float Peser(string Name )
Ecrire
une
fonction
C
qui
à
partir
du
nom
d’un
article
fournit
sa
position
dans
le
tableau
représentant
le
magasin
(-‐1
s’il
n’est
pas
trouvé).
Ecrire
une
fonction
C
qui
à
partir
de
l’indice
d’un
article
et
du
poids
d’une
quantité
de
cet
article,
produit
le
prix
de
cette
quantité.
Ecrire
une
fonction
ou
procédure
qui
à
partir
d’un
tableau
représentant
un
canal
produit
la
valeur
du
débit
courant
global
de
ce
canal
(i.e.
la
somme
des
débits
courants
de
toutes
les
vannes
du
canal).
Ecrire
une
fonction
ou
procédure
qui
à
partir
d’un
tableau
représentant
un
canal,
de
la
valeur
du
débit
courant
de
ce
canal,
et
de
la
valeur
du
débit
mesuré
à
l’amont
de
ce
canal
modifie
les
débits
courant
des
vannes
du
canal.
Cette
action
doit
indiquer
si
tout
l’excédent
ou
tout
le
manque
ont
pu
être
absorbé.
4 0
5
6
7
0
Code de Freeman 0
x
Afin
de
définir
un
point,
nous
utilisons
le
type
Cord
comme
contenant
deux
entiers
représentant
l’abscisse
(x)
et
l’ordonnée
(y)
d’un
point.
Type structuré Cord
Début
Entier x // Entier représentant l’abscisse du point
Entier y // Entier représentant l’ordonnée du point
Fin
h
p
Ecrire
une
fonction
C
qui
à
partir
d’un
tableau
d’entiers
contenant
le
code
de
Freeman
d’un
contour
produit
le
tableau
(tableau
de
valeurs
de
type
Cord).
Le
contour
étant
fermé
l’ordre
des
points
n’a
pas
l
d’importance,
vous
choisirez
la
solution
la
moins
coûteuse.
Ecrire
la
fonction
C
VerifCubo
permettant
de
vérifier
que
la
profondeur
d’un
parallélépipède
est
bien
la
plus
grande
de
ses
dimensions,
et
de
modifier
ses
champs
de
sorte
que
p
soit
la
plus
grande
dimension,
si
ce
n’est
pas
le
cas.
Ecrire
l’action
VolCubo
(fonction
ou
procédure)
permettant
d’obtenir
le
volume
d’un
parallélépipède
(h×l×p).
Ecrire
la
fonction
C
Cubes
permettant
à
partir
d’un
tableau
de
parallélépipède
de
créer
un
tableau
ne
contenant
que
les
cubes
(toutes
ces
faces
sont
carreés).
Ecrire
un
programme
principal
utilisant
les
fonctions
SaisirCubo,
AfficherCubo,
VerifCubo, VolCubo,
et
Cubes qui
:
a. Demande
à
l’utilisateur
un
nombre
de
parallélépipède
à
saisir,
b. Saisit
ces
parallélépipèdes
dans
un
tableau,
c. Corrige
les
parallélépipèdes
non
correctement
saisis
(profondeur
non
correcte),
d. Affiche
l’indice
du
parallélépipède
de
plus
grand
volume,
e. Affiche
les
cubes.
Ecrire
une
fonction
ou
procédure
qui
à
partir
du
tableau
de
variables
de
type
Camionnette,
du
numéro
du
véhicule,
et
d’un
caractère
spécifiant
le
nouveau
statut,
met
à
jour
le
tableau.
Ne
faire
ni
lecture
ni
affichage
dans
cette
action.
On
dispose
du
programme
principal
suivant
:
main( )
{
Camionnette Ent[100] ;
int nbv, j ;
char rep ;
// A compléter
cin >> nbv ;
for ( j=0 ;j<nbv ; j++){
Ent [ j ].Frigo = false ;
Ent [ j ].Statut = 'D' ;
}
// A compléter : définition des camionnettes frigorifiques
cin >> rep ;
while ( rep != 'Q' ) {
// A compléter
cin >> rep ;
}
}
V.
MODULES
RECURSIFS
La
récursivité
est
un
concept
concernant
aussi
bien
des
structures
de
données
que
des
étapes
de
programme.
Ce
concept
consiste
à
définir
directement
ou
indirectement
une
structure
de
données
ou
une
étape
de
programme
en
fonction
d’elle-‐
même.
Un
module
(fonction
ou
procédure)
récursif
est
module
qui
fait
appel
à
lui-‐même
avec
éventuellement
des
paramètres
et/ou
des
valeurs
de
paramètres
différents.
C'est-‐à-‐dire
qu'à
l'intérieur
du
corps
du
module,
il
y
a
au
moins
un
appel
à
lui-‐même.
Il
est
à
noter
que
la
récursivité
n'est
pas
forcément
directe.
En
effet,
un
module
peut
en
appeler
un
autre
qui
en
appelle
un
autre…
qui
finalement
appelle
le
module
d'origine.
Cela
peut
conduire
à
de
la
récursivité
croisée.
Le
cas
élémentaire
de
récursivité
croisée
est
celui
où
un
module
A
appelle
un
module
B
qui
appelle
à
son
tour
le
module
A.
Dans
de
très
nombreux
cas,
l'écriture
récursive
d'un
programme
est
plus
aisée
que
l'écriture
itérative.
Toutefois,
des
précautions
sont
à
observer.
V.2.1. Fonction
FonctionRécursive'
Type)paramètre,)nom)paramètre)
Type)paramètre,)nom)paramètre)
)
Type)paramètre,)nom)paramètre)
)
Type)paramètre,)nom)paramètre)
Type)paramètre,)nom)paramètre)
Type '
Variables)Internes)
)Type)Param)
)… ))
) ))
non)
Condition)arrêt)?)
oui)
Actions)arrêt) Actions)empilement)
Retour) Param))←)FonctionRécursive()liste)paramètres))))
Valeur'Arrêt '
Actions)dépilement)
Retour)
Valeur'dépendant'de'Param '
V.2.2. Procédure
ProcédureRécursive-
Type)paramètre,)nom)paramètre)
Type)paramètre,)nom)paramètre)
)
Type)paramètre,)nom)paramètre)
)
Type)paramètre,)nom)paramètre)
Type)paramètre,)nom)paramètre)
Variables)Internes)
)… ))
) ))
non)
Condition)arrêt)?)
oui)
Actions)arrêt) Actions)empilement)
)ProcédureRécursive)()liste)paramètres))))
Actions)dépilement)
Fin)
Facto"
Factorielle*
Entier)n)
Entier**long *
long factorielle(int n)
Variables)Internes)
)Entier)i )) {
)Entier)long)f) )) int i ;
) )) long f ;
if ( n > 0 )
non) {
n))>)0)?)
f = 1 ;
oui) non)
n))=)0)?) for (i=2 ; i<=n ;i++)
f)←)1) f = f*i ;
return f ;
i)←)2)
oui) } //else inutile
if ( n == 0 )
return 1;
i)≤)n)?)
non) //else inutile
oui) return -1 ;
f)←)f)*)i) }
i)←)i)+)1)
Retour)
*
f Retour)
Retour)
1 *
-1 *
Cette
version
est
très
coûteuse
en
temps
de
calcul
car
elle
multiplie
le
nombre
d’appels
récursifs,
une
version
avec
stockage
des
valeurs
est
plus
adaptée.
Powb
Réel x
Entier n
Réel
float Powb(float x, int n)
{
Variables Internes float p ;
Réel p
if ( n== 0 )
return 1.0 ;
non // else inutile
n =0?
p = Powb( x, n/2 ) ;
oui if ( n % 2 == 0 )
p ← Powb ( x, n div 2 )
return p * p ;
Retour
non // else inutile
n %2=0? return x * p * p ;
1
}
oui
Retour
p*p
Retour
x*p*p
V.3.3.
Fonction
renvoyant
une
solution
s ∈ ]binf, bsup [
d'une
équation
f(x)=0
par
la
méthode
de
dichotomie
à
une
erreur
près,
f
étant
monotone
sur
l’intervalle
de
recherche.
F"
float F(float x)
Réel'x'
{
return x * x -2.0 ;
Réel " }
Retour'
x"*"x"–"2.0 "
Abs#
Dicho&
Réel$binf$
Réel$bsup$
Réel$eps$
Dicho"
Réel$binf$
Réel$bsup$
Réel$eps$
float Dicho(float binf, float bsup,
"
Réel float eps)
$
{
Variables$Internes$ float m ;
$Réel$m $$
$ $$ m = (binf + bsup) / 2.0 ;
$ $$
while ((Abs(binf – bsup) >= eps) &&
m$←$($binf$+$bsup$)$/$2.0$ (Abs(F(m)) >= eps) )
{
if ( F(m) * F(bsup) > 0 )
Abs$($binf$–$bsup$)$≥$eps$$ non$
et$ bsup = m ;
Abs$($F(m)$)$≥$eps$$?$ else
oui$ binf = m ;
}
non$
$F$($m$)$*$F$($bsup$)$>$0$?$ return m ;
}
oui$
bsup$←$m$ binf$←$m$
Retour$
m "
VI. EXERCICES
VI.1.
EXERCICE
1
Les
valeurs
calculées
par
les
suites
de
Fibonacci
sont
obtenues
par
des
relations
de
la
forme
:
f(n)= A.f(n−1)+ B.f(n−2) .
Quels sont les paramètres nécessaires à une fonction permettant de calculer f(n) ?
VI.2.
EXERCICE
2
Les
palindromes
sont
des
mots
se
lisant
aussi
bien
à
l'endroit
qu'à
l'envers
comme
:
LAVAL,
ELLE,
ETE,
KAYAK.
Ecrire
l'entête
et
l'algorithme
d'une
fonction
récursive
booléenne
retournant
vrai
si
une
chaîne
de
caractère
est
un
palindrome
et
faux
sinon.
Ecrire
l’appel
à
cette
fonction.
Traduire
en
langage
C
VI.3.
EXERCICE
3
Ecrire
une
fonction
récursive
booléenne
retournant
vrai
si
les
deux
chaînes
de
caractères
sont
dans
un
ordre
inversé
comme
par
exemple
:
NOEL
et
LEON,
OTAN
et
NATO,
SNOB
et
BONS,
ELLES
et
SELLE…
On
appelle
un
tel
mot
un
anacyclique.
Traduire en langage C. Ecrire un programme principal qui appelle cette fonction.
VI.4.
EXERCICE
4
Ecrire
l'entête
et
l'algorithme
d'une
fonction
récursive
de
recherche
dichotomique
permettant
dans
un
tableau
d'entiers
rangés
dans
l'ordre
croissant
de
MAX
cases
de
retourner
la
place
du
nombre
recherché
ou
une
valeur
négative
si
le
nombre
n'est
pas
dans
le
tableau.
Traduire en langage C. Ecrire un programme principal qui appelle cette fonction.
VI.5.
EXERCICE
5
Ecrire
une
fonction
récursive
booléenne
retournant
vrai
si
les
deux
chaînes
de
caractères
sont
des
anagrammes.
Un
anagramme
est
un
mot
obtenu
par
la
permutation
de
ces
lettres.
Par
exemple
:
chien
et
niche,
crane
et
ecran,
ironique
et
onirique
…
Traduire en langage C. Ecrire un programme principal qui appelle cette fonction.
VI.6.
EXERCICE
6
Ecrire
l'entête
et
l'algorithme
d'une
fonction
récursive
permettant
d’inverser
un
mot.
Par
exemple
:
allumettes
donne
settemulla
…
Traduire en langage C. Ecrire un programme principal qui appelle cette fonction.
VI.7.
EXERCICE
7
Ecrire
l'entête
et
l'algorithme
d'une
fonction
récursive
permettant
de
calculer
la
somme
des
chiffres
d’un
nombre
saisi
comme
une
chaîne
de
caractères.
Par
exemple
:
236714
donne
23…
Traduire
en
langage
C.
Ecrire
un
programme
principal
qui
appelle
cette
fonction.
Remarque
:
une
variable
de
type
char
peut
être
vue
comme
un
entier,
sa
valeur
entière
est
celle
de
son
code
ASCII.
Ainsi,
le
caractère
‘3’
a
pour
valeur
entière
51.
Les
lettres
0
à
9
sont
ordonnées.
Le
code
ASCII
de
‘0’
vaut
48.
Si
on
souhaite
stocker
dans
une
valeur
entière
k
le
nombre
représenté
par
un
caractère
stocké
dans
la
variable
c
il
suffit
d’écrire
:
k
=
c
–‘0’
;
VI.8.
EXERCICE
8
Ecrire
l'entête
et
l'algorithme
d'une
fonction
récursive
permettant
de
dire
si
un
caractère
appartient
ou
non
à
une
chaîne.
Traduire en langage C. Ecrire un programme principal qui appelle cette fonction.
Figure
14
:
Types,
fonctions
et
programme
principal
pour
l’algorithmique
Figure
15
:
Types,
fonctions
et
programme
principal
pour
la
programmation
Ecrire
une
fonction
SaisirTache
permettant
de
saisir
une
variable
de
type
Tache.
Vous
devez
faire
appel
à
la
fonction
SaisirDate.
Compléter
le
programme
principal
afin
de
saisir
des
tâches
tant
que
l’utilisateur
le
souhaite.
Chaque
tâche
saisie
doit
être
stockée
dans
le
tableau
edt,
à
sa
place.
Le
tableau
edt est
classé
par
ordre
croissant
d’heure
de
début.
Vous
devez
faire
appel
à
la
fonction
SaisirTache.
Ecrire
une
fonction
AfficheParJour
permettant
d’afficher
toutes
les
tâches
d’une
journée.
La
date
de
cette
journée
est
passée
en
paramètre
d’entrée.
La
fonction
peut
être
récursive.
Vous
devez
faire
appel
à
la
fonction
AfficheTache.
Compléter
le
programme
principal
afin
de
saisir
une
date
et
d’afficher
toutes
les
tâches
à
effectuer
ce
jour-‐là.
Vous
devez
faire
appel
à
la
fonction
AfficheParJour.
FICHIERS
Les
fichiers
sont
des
ensembles
de
données
sauvegardés
dans
la
mémoire
morte
(disque
dur,
CD,
DVD,
disquette…).
Ces
données
sont
conservées
après
l'arrêt
et
la
fermeture
du
programme
qui
les
a
créées
(programme
fonctionnant
sur
la
mémoire
vive).
Les
fichiers
peuvent
être
utilisés
par
le
programme
ayant
servi
à
leur
création
ou
bien
par
un
autre
programme.
Il
existe
deux
types
de
fichiers
de
données
:
Les
fichiers
au
format
texte
contiennent
des
chaînes
de
caractères
lisibles
par
tout
éditeur
de
texte.
Les
données
y
sont
stockées
sous
la
forme
de
caractères
ASCII
et
sont
des
caractères,
des
chaînes
de
caractères
ou
des
nombres.
Les
fichiers
binaires
contiennent
des
informations
codées
de
la
même
façon
que
dans
la
mémoire
vive
de
l'ordinateur.
Pour
utiliser
les
informations
d'un
fichier,
il
est
nécessaire
d'utiliser
une
variable
servant
d'interface
entre
la
mémoire
vive
(où
s'exécute
le
programme)
et
la
mémoire
morte
(où
est
stocké
le
fichier).
En
C,
il
s'agit
d'un
pointeur
sur
un
fichier.
Cette
notion
de
pointeur
n’ayant
pas
été
étudiée,
et
les
fonctions
utilisées
étant
complexes,
les
fichiers
seront
manipulés
en
langage
C++.
En
C++,
il
s'agit
d'une
«
variable
fichier
».
Les
fonctions
permettant
d'opérer
sur
les
fichiers
appartiennent
à
la
bibliothèque
fstream.
Exemple
:
ofstream monfichier;
fstream f;
Exemples
:
ofstream monfichier;
fstream f;
string nomf = "exercice2.txt";
monfichier.open("c:\TPinfo\TP6\exemple",ios::out|ios::binary);
f.open(nomf.c_str(),ios::in);
III.1.1.
Lecture
variable.read(arg3,arg4); //
lecture
d'octets
du
fichier
arg3:
est
de
type
char*
et
désigne
l'adresse
du
premier
octet
(un
char
est
codé
sur
1
octet)
de
la
zone
mémoire
dans
laquelle
on
va
stocker
les
octets
lus.
On
fait
donc
précéder
la
variable
où
on
stocke
ce
qu’on
lit
de
:
(char*)&
arg4
:
est
d'un
type
entier
et
correspond
au
nombre
d'octets
lus
(et
donc
à
la
taille
de
la
variable
dans
laquelle
on
stocke
ce
qu'on
a
lu).
Ce
nombre
est
obtenu
par
la
fonction
sizeof(…).
Exemple
:
int k;
sonfichier.read((char*)&k, sizeof(k));
III.1.2.
Ecriture
variable.write(arg3,arg4); //
écriture
d'octets
dans
le
fichier
arg3:
est
de
type
char*
et
désigne
l'adresse
du
premier
octet
(un
char
est
codé
sur
1
octet)
de
la
variable
dans
laquelle
sont
stockés
les
octets
à
écrire
dans
le
fichier..
On
fait
donc
précéder
la
variable
contenant
ce
qu’on
écrit
de
:
(char*) &
arg4
:
est
d'un
type
entier
et
correspond
au
nombre
d'octets
à
écrire
dans
le
fichier
(et
donc
à
la
taille
de
la
variable
qu'on
veut
écrire
dans
le
fichier).
Exemple
:
monfichier.write((char*)&k, sizeof(int));
Attention
:
Lorsqu’on
utilise
des
chaînes
de
caractères
et
les
fonctions
de
lecture
et
d’écriture
dans
des
fichiers
binaires,
on
ne
peut
pas
utiliser
le
type string
car
la
fonction
sizeof
ne
peut
pas
déterminer
la
taille
de
la
chaîne,
que
les
chaînes
soient
définies
simplement
ou
dans
un
type
structuré.
Il
faut
définir
les
variables
comme
des
tableaux
de
caractères.
III.1.3.
Remarques
sizeof
est
un
opérateur
unaire
qui
renvoie
le
nombre
d'octets
de
son
opérande,
que
cet
opérande
soit
une
variable
ou
un
type,
simple
ou
structuré.
sizeof(char) donne
le
nombre
d'octets
occupés
par
un
char
(1).
sizeof(k)
donne
le
nombre
d'octets
occupés
par
un
int
(2
ou
4
généralement).
Les
deux
fonctions
(read
et
write)
renvoient
un
booléen
valant
vrai
(!=0 ou true)
lorsque
l'opération
a
réussi
(on
a
pu
lire
ou
écrire
des
données
dans
le
fichier)
ou
faux
(0 ou false)
lorsque
l'opération
a
échoué
(l'écriture
ou
la
lecture
n'ont
pas
été
possibles).
La
principale
raison
de
l'impossibilité
de
lire
des
données
dans
un
fichier
binaire
est
qu'il
n'y
a
plus
rien
à
lire.
Donc,
lorsqu'on
est
en
fin
de
fichier
(parce
qu'il
est
vide
ou
parce
qu'on
a
tout
lu),
la
fonction
read
renvoie
faux
(0 ou
false).
Un
test
sur
la
valeur
renvoyée
par
la
fonction
nous
permet
donc
de
nous
arrêter
en
fin
de
fichier
lors
de
la
lecture
d'un
fichier.
III.1.4.
Exemple
struct article {
char nom[21];
int quantite;
float prix;
};
fstream fich, fach ; //déclaration
des
variables
fichier
struct article art1, art2,art;
cin>>art1.nom>>art1.quantite>>art1.prix; //saisie
des
champs
des
variables
cin>>art2.nom>>art2.quantite>>art2.prix;
fich.open("exemple.bin", ios::out |ios::binary); //ouverture
du
fichier
en
écriture
fich.write((char*)&art1,sizeof(article)); //écriture
d'un
1er
article
fich.write((char*)&art2,sizeof(art2)); //écriture
d'un
2ème
article
fach.open("exemple.bin", ios::in|ios::binary); //ouverture
du
même
fichier,
lecture
while (fach.read((char*)&art,sizeof(article))!=0) //lecture
puis
{ cout<<art.nom<<'\t'<<art.prix<<'\t'; //affichage
de
chaque
article
lu
cout<<art.quantite<<'\n';
}
III.2.1.
Lecture
Pour
la
lecture,
on
utilise
la
variable
fichier,
suivie
de
l'opérateur
>>
puis
des
variables
dans
lesquelles
on
stocke
ce
qu'on
a
lu
dans
le
fichier.
variable >>arg1>>arg2>>…>>argN;
argI
peut
être
une
variable
de
tout
type
pouvant
être
lue
avec
un
cin.
Exemple
:
string chaine;
int m;
f>>chaine>>m;
III.2.2.
Ecriture
Pour
l'écriture,
on
utilise
la
variable
fichier,
suivie
de
l'opérateur
<<
puis
des
variables
à
écrire
dans
le
fichier.
variable <<arg1<<arg2<<…<<argN;
argI
peut
être
une
variable,
une
valeur
ou
une
expression
de
tout
type
pouvant
être
affichée
avec
un
cout.
Exemple
:
g<<"On peut écrire dans le fichier\n";
g<<12<<" + "<<19<<" = "<<12+19;
III.2.3.
Remarques
:
Dans
le
cas
où
des
chaînes
de
caractères
sont
utilisées
pour
l'habillage
du
fichier
(comme
les
" + "
et
" = "
dans
l’exemple
ci-‐dessus),
ces
chaînes
non
porteuses
d'informations
utiles
pour
le
programme
doivent
quand
même
être
lues
et
stockées
dans
des
variables
dont
le
contenu,
bien
sûr,
ne
sera
pas
utilisé.
Elles
ne
serviront
qu'à
la
progression
dans
le
fichier
texte.
Les
espaces
sont
considérés
comme
des
séparateurs
(à
éviter,
ou
à
lire).
Par
exemple,
il
faut
6
lectures
dans
une
chaîne
de
caractères
pour
«
absorber
»
le"On peut écrire dans le fichier".
La
fonction
setw(nb),
avec
nb
une
variable
de
type
entier
ou
un
nombre,
permet
de
formater
le
nombre
de
caractères
pris
en
compte
avec
les
opérateurs
de
flux
<<
et
>>.
Cette
fonction
appartient
à
la
bibliothèque
iomanip.
setw(nb)
permet
d'afficher,
de
lire
ou
d'écrire
une
variable
sur
nb
caractères,
des
espaces
étant
ajoutés
avant
la
valeur
de
la
variable
pour
combler
les
caractères
manquants
(alignement
à
droite).
Exemple
:
cout << setw(4) << 10 ; //
affiche
2
espaces
et
la
valeur
10
VV10
cout << setw(4) << 245 ; //
affiche
1
espace
et
la
valeur
245
V245
Comme
pour
les
fichiers
binaires,
il
est
possible
de
savoir
si
la
lecture
et
l'écriture
ont
échoué.
En
cas
de
réussite,
la
variable
fichier
elle-‐même
vaut
vrai
(!=0 ou true),
sinon
elle
vaut
faux
(0 ou false).
Pour
tester
la
fin
de
fichier,
on
doit
donc
tester
la
variable
elle-‐même.
III.2.4.
Exemple
:
struct article {
char nom[21];
int quantite;
float prix;
};
fstream fich, fach ; //déclaration
des
variables
fichier
struct article art1, art2,art;
cin>>art1.nom>>art1.quantite>>art1.prix; //saisie
des
champs
des
variables
cin>>art2.nom>>art2.quantite>>art2.prix;
fich.open("exemple.txt", ios::out);
fich<<setw(21)<<art1.nom<<setw(5)<<art1.quantite ;
fich <<setw(8)<<art1.prix<<'\n';
fach.open("exemple.txt", ios::in);
while(1)
{ fach>>setw(21)>>art1.nomfach>>setw(5)>>art1.quantite ;
fach >>setw(8)>>art1.prix;
if (fach==0) break; //si
la
lecture
a
échoué,on
sort
de
la
boucle,
sinon
on
affiche
cout<<art1.nom<<'\t'<<art1.prix<<'\t'<<art1.quantite<<'\n';
}
h.open("tests.txt", ios::in);
h>>k;
if(h.eof() != 0) cout << "Fin de fichier atteinte\n";
else cout << "Valeur lue : " << k << "\n" ;
III.4.1.
Exemples
g.close();
monfichier.close();
f.close();
sonfichier.close();
IV. EXERCICES
IV.1.
EXERCICE
1
On
souhaite
informatiser
la
gestion
d'un
magasin
comportant
des
articles
représentés
par
:
un
code,
entier
positif
de
quatre
chiffres
;
un
nom
d'au
maximum
20
caractères
;
un
prix
;
un
stock
de
type
Appro,
dont
le
champ
val
correspond
au
stock
actuel
de
l'article,
et
le
champ
min
au
stock
minimal
en
dessous
duquel
il
faut
réapprovisionner
le
magasin.
La
structuration
des
données
est
la
suivante
:
struct Appro { struct Article {
int val; int code;
int min; char nom[26];
}; float prix;
Appro stock;
};
Exemple
de
données
:
3000
vélo
7
3
299,99
2514
pompe
1
20
6,49
4001
poignée
20
5
6,09
8475
compteur
0
4
21,95
8745
selle
1
6
39,99
Remarque
:
il
est
nécessaire
d’utiliser
la
fonction
setw(… )
dans
les
deux
dernières
questions.
IV.2.
EXERCICE
2
Soit
le
programme
suivant
:
void fonction3 (string r1, objet r2[ ], int r3)
#include <iostream> { fstream W;
#include <string> int k;
#include <fstream> W.open(r1.c_str(), ios::out);
#include <iomanip> for (k=0; k<r3; k++)
using namespace std; {
struct objet W << r2[k].ch1 << " " << r2[k].ch2 << endl;
{ string ch1; }
float ch2; W.close();
}; }
void fonction1(string p1,objet p2[ ],int&p3) void fonction4 (string v1, string v2)
{ fstream D; { fstream A, B;
p3=0; char x[30];
D.open(p1.c_str(), ios::in); float y;
D >> p2[p3].ch1; A.open(v1.c_str(), ios::in);
while(!D.eof()) B.open(v2.c_str(), ios::out);
{ A >> x;
D >> p2[p3].ch2; while ( !A.eof() )
p3++; { A >> y;
D >> p2[p3].ch1; B << x << " " << y << endl;
} A >> x;
D.close(); }
} A.close();
void fonction2 (objet g1[ ], int & g2) B.close();
{ int k, j, m; }
k=0; main ()
while (k<g2) { objet Tab[100];
{ j=k+1; int n, i;
while (j<g2)
{ if (g1[k].ch1 == g1[j].ch1) fonction1 ("UN", Tab, n) ;
{ cout<<"-----------> reponse 1 : "<<n<<endl ;
g1[k].ch2 += g1[j].ch2; cout<<"-----------> reponse 2 : "<<endl ;
for (m=j; m<g2-1; m++) for (i=0 ; i<n ; i++)
{ g1[m] = g1[m+1]; cout<<" "<<Tab[i].ch1<<", "<<Tab[i].ch2<<endl;
} fonction2 (Tab, n) ;
g2--; cout<<"----------> reponse 3 : "<<n<< endl ;
} cout<<"-----------> reponse 4 : "<<endl ;
j++; for (i=0 ; i<n ; i++)
} cout<<" "<<Tab[i].ch1<<", "<<Tab[i].ch2<<endl;
k++; fonction3 ("ANOMMER", Tab, n) ;
} fonction4 ("ANOMMER","UN") ;
} }
Donnez l’affichage suivant reponse 1 et reponse 2. Que fait la fonction fonction1 ?
Donnez l’affichage suivant reponse 3 et reponse 4. Que fait la fonction fonction2 ?
Que
contient
le
fichier ANOMMER après
l’appel
à
la
fonction fonction3 ?
Que
fait
la
fonction
fonction3
?
Que
contiennent
les
fichiers
ANOMMER et
UN
après
l’appel
à
la
fonction
fonction4 ?
Que
fait
la
fonction
fonction4
?
L’appel
à
la
fonction
fonction4
n’était
pas
nécessaire,
dire
comment
modifier
le
programme
pour
qu’il
donne
le
même
résultat
sans
utiliser
la
fonction
fonction4.
IV.3.
EXERCICE
3
On
manipule
dans
cette
question
des
outils
de
coupe
dans
un
atelier.
Un
outil
est
représenté
par
son
nom,
son
code,
sa
durée
de
vie
et
sa
durée
d’utilisation.
Les
durées
sont
exprimées
en
minutes.
Un
booléen
indique
si
l’outil
est
(valeur
vrai)
ou
n’est
pas
utilisable
(valeur
faux,
l’outil
est
usé,
cassé…).
L’atelier
est
représenté
par
un
tableau
d’outils.
On
dispose
du
type
structuré
outil
:
struct outil
{ char nom[26];
int code ;
int dvie ;
int dutil ;
bool ok ;
};
Ecrire
la
fonction
RecupAtelier
qui
produit
un
tableau
d’outils
(atel)
à
partir
d’un
fichier
texte
spécifié
par
son
nom
(nomfich),
le
tableau
contient
alors
nbo
valeurs
:
void RecupAtelier(string nomfich , outil atel[], int & nbo)
Ecrire la fonction AChanger qui stocke dans un fichier binaire tous les outils à changer.
Ecrire la fonction Affiche qui affiche le contenu d’un fichier binaire d’outils à l’écran.
Ecrire
la
fonction
MiseAJour
qui
modifie
la
durée
d’utilisation
d’un
outil
en
fonction
de
la
durée
d’une
tâche.
L’outil
sera
désigné
par
son
code
et
recherché
dans
le
tableau
représentant
l’atelier.
Aucune
saisie,
aucun
affichage
ne
doit
être
fait
dans
cette
fonction.
Le
champ
ok pourra
être
modifié.
Ecrire la fonction Stocke qui stocke le contenu d’un tableau d’outils dans un fichier texte.
IV.4.
EXERCICE
4
Soit
la
fonction
ci-‐contre
:
void fonction ()
Le
fichier
un
a
le
contenu
suivant
:
{ fstream f, g, h;
int i;
9 12 7 21 14 6 -15 -30 28
f.open("un", ios::in);
Les
fichiers
deux et trois sont
vides.
g.open("deux", ios::out|ios::binary);
h.open("trois", ios::out);
f>>i;
while(!f.eof()) {
if(i%2==0) g.write((char*)&i, sizeof(int));
else h<<i<<' ';
f>>i;
}
f.close();
g.close();
h.close();
}
Que contiendront les fichiers un, deux et trois après l'exécution de la fonction fonction ?
IV.5.
EXERCICE
5
Soit
le
programme
C
suivant
manipulant
des
fichiers
:
#include <fstream>
#include <iomanip>
struct MonType
{ int nb ;
float v ;
} ;
void main(void)
{ fstream f1,f2,f3;
MonType val;
f1.open("MonF1", ios::binary | ios::in);
f2.open("MonF2", ios::binary | ios::in);
f3.open("MonF3", ios::out);
while ( f1.read( (char *) &val , sizeof(MonType) ) != 0)
{ f3 << val.nb << " , " << val.v << "\n";
}
while (f2.read( (char *) &val , sizeof(MonType) ) != 0)
{ f3 << val.nb << " , " << val.v << "\n";
}
f1.close();
f2.close();
f3.close();
}
Combien
de
fichiers
ce
programme
manipule-‐t-‐il
?
Précisez
pour
chacun
des
fichiers
son
type,
son
nom
sur
le
disque,
s’il
est
crée,
modifié
ou
lu.
IV.6.
EXERCICE
6
Soient
le
type
structuré
et
les
2
fonctions
suivants
:
struct exemple void A(string B, exemple C[], int &D)
{ int un; { fstream E;
float deux; exemple F;
char trois; int G, H;
}; E.open(B.c_str(), ios::in);
void I(string J, exemple K[], int L) while (! E.eof()) //ou while (E.eof()==false)
{ fstream M; { E>>F.un>>F.deux>>F.trois;
int N; G=0;
while (F.deux>C[G].deux && G<D) G++;
M.open(J.c_str(), ios::out); if(G<D)
for(N=0;N<L;N++) { for(H=D;H>G;H--) C[H]=C[H-1];
{ M<<' '<<K[N].trois; C[G]=F;
M<<' '<<K[N].un; }
M<<' '<<K[N].deux; else C[D]=F;
} D++;
M.close(); }
} E.close();
}
Nous
disposons
de
2
fichiers
:
"examen.txt"
contenant
les
données
de
la
Figure
16
et
"probleme.txt",
pour
l'instant
vide.
Le
programme
étudié
comporte
les
2
variables
suivantes
:
Un
tableau
de
50
cellules,
appelé
DS,
contenant
les
données
de
type
exemple
de
la
Figure
17,
Un
entier
nb
valant
4,
indiquant
le
nombre
de
cellules
du
tableau
DS
occupées,
ainsi
que
les
2
instructions
suivantes
:
1) I("probleme.txt", DS, nb);
2) A("examen.txt", DS, nb);
Représentez le contenu du fichier probleme.txt, à l'issue de l'exécution de la première instruction.
Représentez le fichier examen.txt, tableau DS et la variable nb après l'exécution la deuxième instruction.
IV.7.
EXERCICE
7
On
dispose
du
début
de
programme
suivant,
qui
vise
à
gérer
des
fichiers
contenant
des
modèles
d’appareil
photo
numérique
(APN),
ces
modèles
étant
décrits
par
le
type
photo
composé
de
la
marque,
du
nom
du
modèle,
du
type
d’appareil
(‘C’
pour
appareil
compact
ou
‘R’
pour
appareil
reflex)
et
le
prix
en
euros.
De quel type sont les fichiers f1 et f2 manipulés par la fonction FPhoto ? Que réalise cette fonction ?
On
dispose
des
trois
fichiers
textes
suivants.
Avec
lequel/lesquels
de
ces
fichiers
le
programme
fonctionnera-‐t-‐
il
correctement
?
Justifiez
votre
réponse.
#include<iostream> void FPhoto()
using namespace std; { fstream f1, f2;
#include <iomanip> string nomf1, nomf2;
#include <fstream> photo P;
#include <string> cout << "\nNom du fichier 1 \n";
cin >> nomf1;
struct photo f1.open(nomf1.c_str(), ios::in);
{ cout << "\nNom du fichier 2 \n";
char marque[20] ; cin >> nomf2;
char modele[20] ; f2.open(nomf2.c_str(), ios::out | ios::binary);
char type ; while (1)
float prix ; { f1 >> P.marque;
}; if (f1==0) break;
f1 >> P.modele >> P.type >> P.prix;
void Affiche(photo P) Affiche(P);
{ f2.write((char*)&P,sizeof(photo));
cout <<"\n"<<setw(20)<<P.marque; }
cout <<setw(20)<<P.modele; f1.close();
cout <<" ("<< P.type<<")"; f2.close();
cout <<setw(10)<<"prix : "; cout << "\n\n";
cout <<P.prix<<"\t euros"; }
} main()
{ FPhoto();
}
Fichier photo1.txt
Canon EOS550D R 730.99 Samsung ES74 C 120.33 Nikon D700 R 2100.27
Fichier photo2.txt Fichier photo3.txt
Canon EOS550D R 730.99 Canon EOS550D
Samsung ES74 C 120.33 R 730.99
Nikon D700 R 2100.27 Samsung ES74
C 120.33
Nikon D700
R 2100.27
IV.8.
EXERCICE
8
On
manipule
dans
cette
question
divers
achats
effectués
dans
un
magasin.
Pour
chaque
type
d'article,
on
note
sur
un
ticket
le
prix
unitaire
de
l’article
(champ
Prix
du
type
TypeTicket)
et
le
nombre
d'articles
de
ce
type
achetés
par
le
client
(champ
Nb
du
type
TypeTicket).
On
a
rangé
dans
un
fichier
binaire
nommé
"Jour.bin"
plusieurs
tickets.
On
dispose
du
type
structuré
TypeTicket:
struct TypeTicket
{
float Prix ;
int Nb ;
};
Ecrire
la
fonction
CoutTotal
qui
calcule
le
montant
total
des
achats.
On
doit
parcourir
le
fichier
binaire
et
ne
faire
ni
lecture
au
clavier
ni
affichage
à
l'écran.
IV.9.
EXERCICE
9
On
manipule
dans
cette
question
divers
achats
effectués
dans
un
magasin.
Pour
chaque
type
d'article,
on
note
On
représente
un
individu
par
le
type
structuré
Individu
décrit
sur
la
Figure
18.
Les
fonctions
de
saisie
et
d’affichage
d’un
individu
sont
écrites,
le
programme
principal
est
commencé.
Vous
aurez
à
écrire
une
autre
fonction
et
à
compléter
le
programme
principal.
#include <iostream>
#include <string> void Affich(Individu x)
#include <fstream> {
using namespace std; cout << x.Nom << " a " << x.Age << " ans,";
struct Individu if (x.S == 'F') cout << " elle est ";
{ else cout << " il est ";
char Nom[30]; if (x.Majeur) cout << "majeur";
char S; else cout << "mineur";
int Age; if (x.S == 'F') cout << "e";
bool Majeur; cout << endl;
}; }
Individu Saisie( )
{
Individu x; main ()
cout << "Nom : "; {
cin >> x.Nom; Individu Population[100];
cout << "Age : "; int NbIndiv, i;
cin >> x.Age;
cout << "Sexe : "; // A completer : saisie
cin >> x.S; // A completer : stockage dans fichier indiv.res
return x; // A completer : affichage
}
Figure
18
–
Types,
fonctions
et
programme
principal
pour
la
programmation
Ecrire
une
fonction
Stockage
permettant,
d’affecter
le
champ
Majeur
de
chaque
individu
contenu
dans
un
tableau
d’individus
à
true
ou
à
false
en
fonction
de
son
âge,
et
de
stocker
dans
un
fichier
binaire
ce
tableau
d’individus.
Compléter
le
programme
principal
afin
de
saisir
des
individus
dans
le
tableau
Population
(appel
à
Saisie)
puis
d’appeler
la
fonction
Stockage,
et
enfin
d’afficher
les
individus
du
tableau
(appel
à
Affich).
I. GENERALITES
I.1.
INTRODUCTION
Supposons
que
l’on
travaille
sur
un
projet
de
gestion
de
trafic
sur
une
voirie
pour
lequel
la
représentation
de
feux
tricolores
est
nécessaire.
Dans
le
cahier
des
charges
de
ce
projet
il
est
stipulé
qu'un
feu
tricolore
est
toujours
allumé,
il
ne
peut
donc
être
qu’au
vert,
à
l’orange
ou
au
rouge
(la
situation
où
il
est
éteint
n'est
pas
envisagée).
De
plus,
l'orange
clignotant
n'existe
pas.
Les
actions
possibles
sur
un
feu
sont
:
Passer_Vert
:
met
le
feu
au
vert,
Passer_Orange
:
met
le
feu
à
l'orange,
Passer_Rouge
:
met
le
feu
au
rouge.
On
peut
avoir
besoin
de
savoir
si
le
feu
est
au
rouge
ou
au
vert.
S'il
n'est
ni
l'un
ni
l'autre,
il
est
donc
orange.
Pour
cela,
on
définit
deux
tests
:
Est_Vert
:
qui
produit
la
valeur
vrai
si
le
feu
est
au
vert
et
la
valeur
faux
sinon,
Est_Rouge
:
qui
produit
la
valeur
vrai
si
le
feu
est
au
rouge
et
la
valeur
faux
sinon,
Le
feu
ne
peut
passer
que
du
vert
à
l’orange,
de
l’orange
au
rouge
et
du
rouge
au
vert.
Lors
de
sa
première
utilisation,
il
est
forcé
au
rouge.
De
par
leur
définition,
les
actions
et
tests
sont
liés
par
des
relations
(le
test
Est_Rouge
précèdera
toujours
Passer_Vert).
De
même,
certaines
combinaisons
d'actions
et
de
tests
sont
impossibles
(Passer_Vert
et
Passer_Rouge
ne
peuvent
pas
se
succéder).
Il
est
alors
possible
de
résumer
ce
qui
définit
un
feu
tricolore
par
la
spécification
décrite
page
suivante
dans
laquelle
les
opérations
possibles
et
impossibles
sont
précisées.
Nous
venons
ainsi
de
définir
un
Type
de
Donnée
Abstrait
(TDA)
qui
est
"feu
tricolore"
qui
peut
être
spécifié
différemment
sans
que
les
données
du
problème
de
gestion
de
trafic
ne
soient
modifiées.
La
définition,
la
spécification
et
l'implémentation
du
TDA
Feu
Tricolore
sont
indépendantes
du
projet
de
gestion
du
trafic
et
peuvent
être
modifiées
sans
impact
sur
le
projet.
II.1.
DEFINITION
Les
éléments
contenus
dans
une
pile
sont
dits
"empilés".
Ils
sont
ajoutés
en
sommet
de
pile
et
retirés
à
partir
du
sommet
de
la
pile,
comme
dans
une
pile
d'assiette
où,
pour
accéder
à
l'assiette
du
bas,
il
faut
retirer
toutes
les
assiettes
posées
dessus
afin
de
ne
pas
les
casser.
La
gestion
des
piles
est
de
type
LIFO
("Last
In
First
Out"
:
dernier
entré
premier
sorti).
Les
actions
principales
menées
sur
les
piles
sont
:
l'initialisation
d'une
pile,
l'ajout
d'un
élément,
le
retrait
d'un
élément,
la
vérification
que
la
pile
est
vide,
l'accès
au
sommet
de
la
pile.
D'autres
opérations
peuvent
être
définies
sur
une
pile.
Elément( Elément(
Elément( Elément(
Figure
19
:
Illustration
d'une
pile.
La spécification du TDA Pile qui découle de ce qui vient d'être décrit est la suivante.
II.3.
PROGRAMMATION
Une
pile
est
représentée
par
:
• L'ensemble
de
ses
éléments,
dans
l'ordre
de
leur
ajout,
• Un
repère
sur
l'élément
du
sommet,
les
autres
éléments
étant
dessous.
0 1 2 3 4 5 6 7
Elt 0.6 -2.7 16.9 2.8 3.1
Sommet
Figure
20.
Implémentation
d'une
pile
de
réels.
II.3.2.
Opérations
Les
différentes
opérations
étudiées
précédemment
doivent
être
programmées.
Du
fait
du
choix
d'un
tableau
pour
stocker
les
éléments
de
la
pile,
notre
pile
peut
être
pleine,
car
la
taille
du
tableau
est
finie.
Il
faudra
programmer
une
autre
opération
testant
si
la
pile
est
pleine.
Les
opérations
effectuées
sur
la
pile
sont
des
fonctions.
Elles
sont
indépendantes
du
type
de
données
réellement
contenues
dans
la
pile.
II.3.2.2. Fonction
vérifiant
si
la
pile
est
pleine
//
Nécessaire
pour
la
traduction
bool Full (Pile P)
{
return (P.Sommet==NMAX) ;
}
0 1 2 3 4 5 6 7
Retrait
Elt 0.6 -2.7 16.9 2.8 3.1
d'un
élément
sommet sommet
3.1
0 1 2 3 4 5 6 7
Ajout
Elt 0.6 -2.7 16.9 2.8 14.8
d'un
élément
sommet sommet
14.8
Figure 21. Retrait et Ajout d'un élément dans une pile de réels.
II.3.2.3. Fonction
d'ajout
d'un
élément
dans
la
pile
(voir
Figure
21)
void Ajouter (Element nouveau, Pile & P)
{
P.Elt[P.Sommet]=nouveau ;
(P.Sommet)++ ;
}
II.3.2.4. Fonction
de
sortie
d'un
élément
de
lapile
(voir
Figure
21)
Element Retirer(Pile & P)
{ (P.Sommet)-- ;
return P.Elt[P.Sommet] ;
}
III.1.
DEFINITIONS
La
gestion
des
files
est
de
type
FIFO
("First
In
First
Out"
:
premier
entré
premier
sorti).
Les
éléments
sont
entrés
en
queue
de
file
et
sortis
en
tête
de
file.
Ce
TDA
correspond
à
une
file
d'attente
à
une
caisse
de
supermarché.
Les
actions
principales
menées
sur
les
files
sont
:
l'initialisation
d'une
file,
l'ajout
d'un
élément,
le
retrait
d'un
élément,
la
vérification
que
la
file
est
vide,
l'accès
à
la
tête.
D'autres
opérations
peuvent
être
définies
sur
une
file.
Description
des
cinq
opérations
précédentes
:
Initialisation
d'une
file
:
Init
Cette
action
permet
d'initialiser
une
file.
Elle
ne
contient
alors
aucun
élément
et
pourra
par
la
suite
contenir
des
éléments.
Ajouter
un
élément
:
Ajouter
Cette
action
permet
d'ajouter
un
élément
en
queue
d'une
file.
Le
détail
de
cette
opération
est
montré
sur
la
Figure
22.
Retrait
d'un
élément
:
Retirer
Cette
action
permet
de
retirer
l'élément
placé
en
tête
d'une
file.
Le
détail
de
cette
opération
est
montré
sur
la
Figure
22
Vérification
que
la
file
est
vide
:
Vide
Cette
action
produit
la
valeur
booléenne
vrai
si
la
file
ne
contient
pas
d'élément
et
faux
sinon.
Accès
à
la
tête
:
Tete
Cette
action
produit
l'élément
placé
en
tête
de
file
sans
le
retirer.
Elément(
Ajou
ter(
Fin( Elém
( ent
(
Elém
( e nt(
Elément(
Elém
( e nt( (
Elém
( e nt( (
Tête e tirer
( R
Figure
22.
Illustration
d'une
file.
La spécification du TDA File qui découle de ce qui vient d'être décrit est la suivante.
III.3. PROGRAMMATION
III.3.1.
Introduction
Pour
représenter
une
file,
on
a
besoin
de
:
L'ensemble
des
éléments
de
la
file,
dans
l'ordre
de
leur
ajout,
Un
repère
sur
le
début
de
la
file
d'où
sont
retirés
les
éléments,
Un
repère
sur
la
fin
de
la
file
où
sont
ajoutés
les
éléments.
Si
l'on
représente
l'ensemble
des
éléments
par
un
tableau,
la
file
va
alors
ressembler
à
la
partie
gauche
de
la
Figure
23.
Lorsqu'on
ajoute
un
élément
dans
la
file,
la
fin
de
la
file
est
décalée
(voir
partie
droite
de
la
Figure
23).
0 1 2 3 4 5 0 1 2 3 4 5
E1 E2 E3 E4 E1 E2 E3 E4 E5
Si
l'on
retire
maintenant
un
élément
de
la
file
(l'élément
E1
qui
est
position
d'être
retiré),
deux
possibilités
s'offrent
à
nous
:
Retirer
l'élément
puis
décaler
toute
la
file
afin
que
le
prochain
élément
à
retirer
soit
toujours
à
la
même
position
dans
le
tableau
(voir
Figure
24
partie
gauche).
Ce
fonctionnement
correspond
à
une
file
d'attente
en
caisse
de
supermarché
où
le
prochain
client
s'avance
jusqu'à
la
caisse
et
les
suivants
se
déplacent.
Retirer
l'élément
puis
décaler
le
début
de
la
file
afin
qu'il
indique
le
prochain
élément
à
retirer
(voir
Figure
24
partie
droite).
Ce
fonctionnement
correspond
à
un
contrôle
de
papiers
de
véhicule
en
bord
de
route,
où
le
gendarme
se
déplace
d'une
voiture
à
l'autre,
dans
l'ordre
de
leur
arrivée.
0 1 2 3 4 5 0 1 2 3 4 5
E2 E3 E4 E5 E2 E3 E4 E5
Le
fonctionnement
de
la
partie
gauche
de
la
Figure
24
correspond
à
une
file
linéaire.
Le
fonctionnement
de
la
partie
droite
de
la
Figure
24
correspond
à
une
file
circulaire
(car
la
file
va
avancer
dans
le
tableau
jusqu'à
arriver
au
bout
et
revenir
au
début).
III.3.2.1. Représentation
Les
éléments
de
la
file
étant
toujours
retirés
de
la
même
case,
une
file
est
représentée
par
:
un
tableau
d'éléments,
l'indice
de
la
fin
de
la
file.
Le
contenu
de
la
file
sera
toujours
de
type
Element
;
l'indice
de
fin
est
l'indice
du
premier
emplacement
libre.
typedef type Element;
struct File
{
Element Elt[NMAX];
int Fin;
};
Exemple
:
#define NMAX 20
typedef float Element;
struct File
{ Element Elt[NMAX];
int Fin;
};
0 1 2 3 4 5 6 7
Elt 4.7 -9.1 18.5 -14.6 1.2
Fin
III.3.2.2. Opérations
Tout
comme
pour
le
TDA
pile,
les
éléments
étant
stockés
dans
un
tableau,
un
test
de
file
pleine
doit
être
programmé.
File
vide
bool EstVide (File F)
{ return ( F.Fin == 0 ) ;
}
Figure 26. Retrait et Ajout d'un élément dans une file linéaire de réels.
III.3.3.1. Représentation
Afin
d'éviter
le
décalage
de
tous
les
éléments
de
la
file
à
chaque
retrait,
on
fait
varier
le
début
de
la
file
dans
le
tableau.
La
file
est
alors
composée
de
:
un
tableau
d'éléments,
un
indice
de
fin,
un
indice
de
début.
L'indice
de
fin
est
en
fait
l'indice
du
premier
emplacement
libre
;
l'indice
de
début
est
l'indice
du
prochain
élément
qui
sortira.
Lorsque
la
fin
ou
le
début
de
la
file
arrive
à
la
dernière
case
du
tableau,
on
retourne
à
la
première
case
du
tableau
(ainsi
la
file
avance
et
tourne
en
rond
dans
le
tableau).
typedef type Element;
struct File
{
Element Elt[NMAX];
int Debut;
int Fin;
};
Exemple
:
#define NMAX 20
typedef float Element;
struct File
{
Element Elt[NMAX];
int Fin, Debut;
};
0 1 2 3 4 5 6 7
Elt -9.1 18.5 -14.6 1.2
Debut Fin
III.3.3.2. Opérations
Le
tableau
impose
de
tester
si
la
file
est
pleine
ou
pas.
En
outre,
la
file
se
décalant
dans
le
tableau,
il
est
nécessaire
de
conserver
une
case
vide
entre
le
début
et
la
fin
de
la
file,
afin
de
différencier
la
file
vide
de
la
file
pleine
(le
cas
où
le
début
rejoint
la
fin
doit
être
différent
du
cas
où
la
fin
rejoint
le
début).
File
vide
bool vide (File F)
{ return ( F.Fin == F.Debut ) ;
}
0 1 2 3 4 5 6
Cas
1
elements 18.5 -14.6 1.2 27.8 4.7 -9.1
fin debut
0 1 2 3 4 5 6
Cas
2
elements 4.7 -9.1 18.5 -14.6 1.2 27.8
debut fin
0 1 2 3 4 5 6
Cas
3
elements 4.7 -9.1 18.5 -14.6 1.2 27.8
fin debut
Figure 29. Ajout d'un élément dans une file circulaire de réels.
0 1 2 3 4 5 6 7
Retrait
d'un
élément
elements 4.7 -9.1 18.5 -14.6 1.2
Cas
1
debut debut fin
4.7
0 1 2 3 4 5 6 7
Retrait
d'un
élément
elements 1.2 27.8 -9.1 -14.6 18.5
Cas
2
debut fin debut
18.5
Figure 30. Retrait d'un élément dans une file circulaire de réels.
IV. EXERCICES
IV.1.
EXERCICE
1
Définir
un
TDA
représentant
une
pièce
de
monnaie
ne
pouvant
pas
être
posée
sur
la
tranche
:
IV.2.
EXERCICE
3
Ecrire
une
fonction
permettant
de
donner
le
rang
d'un
élément
donné
dans
une
pile.
Ecrire une fonction permettant de compter le nombre d'éléments contenu dans une pile.
Ecrire une fonction permettant de donner le rang d'un élément donné dans une file.
Ecrire une fonction permettant de compter le nombre d'éléments contenu dans une file.
IV.3.
EXERCICE
2
A
partir
du
TDA
feu
tricolore
du
cours,
écrire
l'algorithme
de
l'opération
Changer_Couleur
qui
fait
passer
du
vert
à
l'orange,
de
l'orange
au
rouge
ou
du
rouge
au
vert.
On
suppose
maintenant
que
dans
le
projet
de
gestion
de
trafic,
la
seule
action
possible
sur
le
feu
est
l’action
Changer_Couleur
qui
met
le
feu
au
vert
s’il
était
rouge,
à
l’orange
s’il
était
vert
et
au
rouge
s’il
était
orange.
Les
actions
Passer_Orange,
Passer_Rouge
et
Passer_Vert
ne
sont
plus
accessibles.
Réécrire
le
TDA
feu
tricolore
du
cours.
Ecrire
les
algorithmes
des
actions
Forcer_Vert,
Forcer_Rouge
et
Forcer_Orange
avec
cette
nouvelle
spécification.
IV.4.
EXERCICE
4
Ecrire
une
fonction
itérative
permettant
d’afficher
les
éléments
d’une
pile
dans
l’ordre
de
parcours.
Ecrire une fonction itérative permettant d’afficher les éléments d’une file dans l’ordre de parcours.
IV.5.
EXERCICE
6
Un
logiciel
de
planification
envoie
des
tâches
à
réaliser
sur
différents
postes
de
travail.
Chaque
poste
de
travail
comporte
deux
opérateurs.
Chaque
tâche
envoyée
à
un
poste
comporte
donc
le
numéro
de
l'opérateur
et
la
durée
de
la
tâche.
Les
tâches
sont
mises
en
file
d'attente
sur
le
poste
de
travail
où
elles
seront
dispatchées
sur
l'un
ou
l'autre
des
opérateurs
lors
du
traitement
de
la
liste
de
tâches.
Nous
gérons
un
poste
de
travail
comportant
2
opérateurs.
Il
y
a
donc
trois
files
de
tâches
:
La
file
des
tâches
à
traiter,
La
file
des
tâches
à
réaliser
par
l'opérateur
1,
La
file
des
tâches
à
réaliser
par
l'opérateur
2.
Ecrivez
un
algorithme
puis
un
programme
en
langage
C
effectuant
les
actions
suivantes
:
1) Création
et
déclaration
du
type
des
données
stockées
dans
la
file,
2) Déclaration
et
initialisation
des
3
variables
de
type
File
nécessaires
(linéaire
ou
circulaire,
au
choix),
3) Saisie
des
tâches
du
poste
de
travail
pour
la
journée
(en
remplacement
de
l'envoi
des
tâches
par
le
planificateur),
4) Lecture
de
chaque
tâche
et
affectation
à
l'opérateur
(retrait
puis
ajout
dans
2
files),
5) Affichage
des
tâches
de
l'opérateur
1
et
de
sa
durée
totale
de
travail,
6) Affichage
des
tâches
et
de
la
durée
de
travail
de
l'opérateur
2.
IV.6.
EXERCICE
8
Ecrire
une
fonction
récursive
permettant
d’afficher
les
éléments
d’une
pile
dans
l’ordre
de
parcours.
Ecrire une fonction récursive permettant d’afficher les éléments d’une file dans l’ordre de parcours.
Ecrire une fonction récursive permettant d’afficher les éléments d’une pile dans l’ordre inverse de parcours.
Ecrire une fonction récursive permettant d’afficher les éléments d’une pile dans l’ordre inverse de parcours.
IV.8.
EXERCICE
7
On
considère
le
type
structuré
UneVoiture
défini
ci-‐dessous.
Type structuré UneVoiture
Début
Chaîne modele
Entier km
Entier annee
Fin
Ecrire
une
action
truc1
(procédure
ou
fonction)
qui,
à
partir
d’un
tableau
de
UneVoiture
(type
décrit
ci-‐dessus)
fournit
une
pile
contenant
l’ensemble
des
UneVoiture
du
tableau
dont
le
kilométrage
est
compris
entre
deux
valeurs
spécifiées.
Cette
action
doit
fournir
le
nombre
de
UneVoiture
contenues
dans
la
pile
(c’est-‐à-‐dire
le
nombre
de
UneVoiture
dont
le
kilométrage
est
compris
entre
les
valeurs
spécifiées).
Quelle(s)
modification(s)
sont
à
apporter
à
cette
action
si
le
critère
de
recherche
est
l’année
du
véhicule
(indiquez
uniquement
les
lignes
modifiées)
?
L’action
ainsi
modifiée
est
appelée
truc2.
Act1 début
File A
Elément B Variables Internes
Pile C Entiers m, j, f, d, r
File k
Pile t
Variables Internes
Elément x
Init ( k )
Saisir m
Init ( C )
non j!1
non Vide(A) ?
non
oui j≤m?
oui
x ← Retirer ( A )
Saisir f
non
x≠B? Ajouter ( f, k )
oui
j ← j +1
Ajouter ( x , C )
Saisir d
non
Fin d>0?
oui
r ← Act2 ( k , d )
Act2
File A
Afficher r
Elément B
Act1 ( k , d , t )
Entier non
non Vide( A ) ? j!1
oui non
j≤r?
non
Tete( A ) ≠ B ? oui
oui Afficher Retirer ( t )
Retirer ( A ) Retirer ( A )
j ← j +1
Retour Retour
1 + Act2 ( A , B ) Act2 ( A , B )
Retour Saisir d
0
Fin
Figure
31
–
Procédure
Act1,
fonction
Act2
et
programme
principal.
On
lance
le
programme
principal
et
on
donne
les
valeurs
successives
suivantes
pour
m,
f
puis
d
:
{
5,
3,
8,
3,
4,
9,
4,
3,
-‐1
}.
Quelles
valeurs
seront
écrites
à
l’écran
?
Détaillez
et
justifiez
vos
réponses
en
donnant
par
exemple
le
contenu
des
files
et
piles
au
fur
et
à
mesure
de
l’exécution.
IV.12.
EXERCICE
9
Ecrire
une
fonction
qui
compte
le
nombre
de
valeurs
égales
à
val
dans
un
tableau
t
de
nb
entiers.
Cette
fonction
ne
doit
faire
ni
saisie
(lecture)
ni
affichage
(écriture).
L’entête
de
cette
fonction
est
la
suivante:
int compte ( int t [ ], int nb, int val)
Pour
les
questions
suivantes,
on
utilise
le
TDA
Pile
défini
dans
le
cours.
On
considère
que
le
type
élément
est
assimilé
au
type
Entier.
Ecrire
un
module
(une
fonction
ou
une
procédure)
récursif
qui
permet
d’afficher
les
éléments
(entiers)
contenus
dans
une
pile.
Ecrire
un
module
(une
fonction
ou
une
procédure)
qui
à
partir
d’un
tableau
d’entiers
et
d’une
valeur
crée
une
pile
contenant
les
éléments
du
tableau
différents
de
cette
valeur.
Ce
module
ne
doit
faire
ni
saisie
(lecture)
ni
affichage
(écriture).
On
suppose
déjà
écrit
le
début
de
programme
C
suivant
:
#include <iostream>
using namespace std ;
main()
{ int Tab[40], n, i ;
// A compléter
cout << " Entrer le nombre d’éléments à saisir " ;
cin >> n ;
for ( i=0 ; i<n ; i++ ) cin >> Tab[i] ;
// A compléter
}
Quel
est
le
contenu
des
piles
Z1
et
Z2
après
l’instruction
suivante
ExoA ( F1 , 9, Z1, Z2 ) ?
Détaillez
votre
réponse.
Combien
d’appels
à
ExoA et
à
ExoB sont-‐ils
effectués
?
Quel est le contenu des listes Z3 et Z4 après l’instruction suivante ExoA ( F1 , 41, Z3, Z4 ) ? Détaillez.
Quel est le contenu des listes Z5 et Z6 après l’instruction suivante ExoA ( F1 , 3, Z5, Z6 ) ? Détaillez.
Modifier
la
procédure
ExoA
ou
la
procédure
ExoB
ou
les
deux,
pour
que
l’ordre
de
traitement
des
éléments
des
piles
soit
le
même
que
celui
des
éléments
de
la
file
initiale.
ExoA ExoB
File A File R
Entier v
Pile B Pile K
Pile C
Init ( K )
Variables Internes
Entier x non
non Vide ( R ) ?
non oui
Vide ( A ) ?
Ajouter ( Tete( R ) , K )
oui non
Tete ( A ) = v ?
Init ( B ) Retirer ( R )
oui x ← Retirer ( A )
Init ( B ) Fin
Ajouter ( x , B )
Fin
Figure
32
–
File
F1.
Quelles valeurs seront écrites à l’écran ? Détaillez et justifiez vos réponses.
Que font les actions Aff, Compte et range ? Précisez pour chacune si elle est récursive ou itérative.
Compte début
Type structuré Elément
début
File R
chaîne Code Variables
Entier Type Elément Val
Réel
Réel Tps Entier n, j
Fin Réel r
Variables Internes
Pile A
Réel Inter
File R
non
non Vide (R) ? Init ( A )
oui
Pile A j!1
Entier T Retour
Inter + Compte ( R ) non
File Retour j≤n?
0 oui
Variables Internes
Elément E Saisir Val.Code
File F Saisir Val.Type
Aff Saisir Val.Tps
Init ( F )
File X
Ajouter ( Val, A )
non
non Vide (A) ?
Variables Internes j ! j +1
oui Réel V
E ! Retirer ( A )
non R ! Range ( A , 2 )
E.Type = T ? non Vide (X) ?
Retour
F Fin Fin
Figure
33
–
Procédure
Aff,
fonctions
Range
et
Compte,
et
programme
principal.
Prepare
début File A
Element T
Variables Internes
Elément X, V
File K Variables Internes
File F
Init ( K )
Init ( F )
Saisir X.Code
non
T.Prio = 0 ?
X.Code ≠ "stop" ? oui
oui non
non Vide (A) ?
Saisir X.Prio
oui
Saisir X.Code
Ajouter ( T , A ) Ajouter(T , A )
Afficher V.Code
Fin Fin
Figure
34
–
Procédure
Prepare
et
programme
principal.
On
lance
le
programme
principal
et
on
donne
les
valeurs
successives
suivantes
:
{ "Salles", 1,
"Riley", 4,
"Stewart", 0,
"Hedlund", 2,
"stop" }.
Donnez l’évolution de la file K au fur et à mesure des saisies.