Vous êtes sur la page 1sur 195

1 Programme, algorithmes, langage de program-

mation
1.1 Informatique
– Définition de l’informatique :

Ensembles des techniques de la mise en mémoire et de l’utilisation


des informations traitées automatiquement à l’aide de programmes
mis en œuvre sur ordinateurs.

– Ordinateur :

– garde des nombres en mémoire


– fait des calculs sur des nombres
– a des instructions pour lui demander d’accéder aux données en mé-
moire et de faire des calculs

1. Algorithmique et programmation – L1 Stéphane Rivière


– Programme :

– liste d’instructions demandant de faire certains calculs sur certaines


données
– écrit une fois pour toute pour pouvoir être exécuté quand on veut

– Algorithmes : méthodes qui permettent de

– modéliser le problème : le représenter par des nombres

– quelles sont les données d’entrée à partir desquelles faire les calculs
– quelles sont les données résultat voulues en sortie

– résoudre le problème : savoir quels calculs faire pour obtenir les don-
nées résultat à partir des données d’entrée

2. Algorithmique et programmation – L1 Stéphane Rivière


– Outils de base des algorithmes :
– faire des calculs sur des données : types et expressions
– stocker des valeurs en mémoire : variables
– demander des valeurs à l’utilisateur, les afficher : entrées/sorties
– exécuter de façon conditionnelle des instructions (c.-à-d. en fonction
de résultats de tests) : instructions conditionnelles
– répéter l’exécution d’instructions : instructions itératives
– isoler des instructions pour pouvoir les réutiliser plus facilement : fonc-
tions et procédures
– rassembler plus facilement des ensembles de données : structures et
tableaux
– Langage algorithmique :
– langage informel de haut niveau proche du langage humain
– qui permet de représenter les outils algorithmiques

3. Algorithmique et programmation – L1 Stéphane Rivière


1.2 Langage de programmation
– Un ordinateur (un processeur) possède un langage de programmation : le
langage machine (assembleur)

– chaque instruction est représentée par un numéro (un symbole)


– instructions de bas niveaux : très précises, spécifiques au processeur
– impossible en pratique d’écrire des gros programmes en langage ma-
chine

→ On utilise un langage de programmation :

– langage plus proche du langage humain mais avec une syntaxe précise
– transformé en langage machine grâce à un compilateur

– On utilisera le langage C++ et le logiciel Code : :Blocks (codeblocks.org)


pour écrire les programmes en C++, les compiler et les exécuter

4. Algorithmique et programmation – L1 Stéphane Rivière


2 Structure d’un programme C++
#include<iostream> <-- bibliothèques utilisées
#include<string>
using namespace std; <-- pour utiliser bibliothèques

/* <-- commentaire bloc


programme qui demande le nom de l’utilisateur
et affiche un message de bienvenue
*/

int main() <-- programme principal


{
//demander le nom de la personne <-- commentaire en ligne
string nom; <-- déclaration de variable
cout<<"votre nom : "; <-- affichage
cin>>nom; <-- lecture de données
//afficher le message de bienvenue
cout<<"bonjour "<<nom<<" j’espère que vous allez bien"<<endl;
}

5. Algorithmique et programmation – L1 Stéphane Rivière


2.1 Bases d’un programme C++
1. Bibliothèques :
– utilitaires (fonctions, procédures) supplémentaires n’existant pas dans
le langage de base
– pour utiliser une bibliothèque : #include<nom bibliothèque>
– à la fin des bibliothèques : using namespace std;
2. Programme principal :
– c’est lui qui est exécuté quand on lance le programme
int main()
{
instructions du programme
}

3. Une fois le programme écrit (dans un fichier .cpp), il faut le compiler puis
l’exécuter.

6. Algorithmique et programmation – L1 Stéphane Rivière


2.2 Écriture en C++
– Indentation : mise en page (espaces, retour à la ligne)
– en C++ l’indentation n’est pas importante : il faut juste respecter la
syntaxe
– mais l’indentation est importante pour l’utilisateur : elle donne l’aspect
visuel et donc aide la lecture et la compréhension d’un programme
→ respecter des règles d’indentation
– Commentaires : texte ignoré par le compilateur contenant des indications
pour celui qui lit le programme
– commentaire sur une ligne : // à partir de là : commentaire
– bloc de commentaires :
/*
commentaires
*/

7. Algorithmique et programmation – L1 Stéphane Rivière


3 Types et expressions
3.1 Types
– Les valeurs avec lesquelles on fait des calculs sont classées en différents
types de valeurs
– Un type définit :

– les valeurs possibles : format, représentation en mémoire (et donc taille


et valeurs limites)
– les opérations que l’on a le droit d’effectuer sur ces valeurs

– On utilisera en C++ 5 types principaux :


booléens bool
types discrets caractères char
entiers int types
réels en virgule flottante double arithmétiques
chaînes de caractères string

8. Algorithmique et programmation – L1 Stéphane Rivière


– Valeurs littérales des différents types :

Type Type C++ Valeurs littérales


entiers int 0 123 -3248
1.23 .23 0.23 1. 1.0
réels double
1.2e10 1.23e-15
booléens bool false ou true
caractères char ’a’ ’;’ ’\t’
chaînes de string "bonjour" "" "c’est \"mauvais\""
caractères

9. Algorithmique et programmation – L1 Stéphane Rivière


3.2 Expressions
– Une expression est un calcul sur des valeurs dont le résultat est une valeur
– Les valeurs proviennent de

– valeur littérale
– valeur stockée dans une variable
– valeur résultat d’un calcul : expression

– On peut faire des calculs grâce aux

– opérateurs
– fonctions

10. Algorithmique et programmation – L1 Stéphane Rivière


3.2.1 Opérateurs

Opérateur C++
multiplication expr * expr
division expr / expr
reste euclidien (modulo) expr % expr
addition expr + expr
soustraction expr - expr
moins unaire - expr

– Les opérateurs dans une même case ont la même priorité, les cases sont
classés par ordre de priorité décroissant : a+b*c signifie a+(b*c)
– Ces opérateurs sont associatifs à gauche : a+b+c signifie (a+b)+c
– Des parenthèses peuvent être utilisées pour forcer l’ordre d’évaluation
!! La division entre deux entiers renvoie le quotient entier de la division eu-
clidienne : 23 / 3 → 7, et 23 % 3 → 2

11. Algorithmique et programmation – L1 Stéphane Rivière


3.2.2 Les fonctions mathématiques
– Les fonctions mathématiques usuelles sont fournies par la bibliothèque
cmath
– Il n’y a pas de fonction « au carré ».

double abs(double); valeur absolue


double fabs(double);
double ceil(double d); plus petit entier ≥ d
double floor(double d); plus grand entier ≤ d
double sqrt(double d); racine carrée, d≥0
double pow(double d,double e); d puissance e
double pow(double d,int i); d puissance i

12. Algorithmique et programmation – L1 Stéphane Rivière


double cos(double); cosinus
double sin(double); sinus
double tan(double); tangente
double acos(double); arc cosinus
double asin(double); arc sinus
double atan(double); arc tangente
double atan2(double x,double y); atan(x/y)
double sinh(double); sinus hyperbolique
double cosh(double); cosinus hyperbolique
double tanh(double); tangente hyperbolique
double exp(double); exponentielle, base e
double log(double d); logarithme népérien (base e), d>0
double log10(double); logarithme base 10

13. Algorithmique et programmation – L1 Stéphane Rivière


4 Instructions
– Une expression est un calcul qui donne une valeur
– Une instruction est un ordre à exécuter, par exemple

– déclarer une variable


– afficher une valeur
– lire une valeur tapée au clavier

– En C++ une instruction est toujours terminée par un point-virgule « ; »


– Pour faire exécuter plusieurs instructions : les écrire dans l’ordre d’exécu-
tion

instruction1 ;
instruction2 ;
...

14. Algorithmique et programmation – L1 Stéphane Rivière


5 Variables et constantes
5.1 variables
– Une variable est une case mémoire qui permet de stocker une valeur
– Elle sert à

– garder en mémoire une valeur que l’on veut utiliser plusieurs fois
– calculer une valeur en plusieurs étapes (en permettant de garder en
mémoire le résultat de l’étape précédente)
– stocker en mémoire les valeurs rentrées par l’utilisateur
– découper un calcul compliqué

15. Algorithmique et programmation – L1 Stéphane Rivière


– Pour pouvoir utiliser une variable, il faut d’abord la déclarer :

– donner son nom (pour pouvoir l’utiliser ensuite), un nom intelligent


qui décrit ce qu’elle contient
– donner son type (pour savoir le type de la valeur contenue)
– éventuellement donner une valeur d’initialisation (une variable non
initialisée contient n’importe quoi)

– déclarer une variable est une instruction


– en algorithmique :

– variable type nom (=valeur initialisation )


– p.ex. : variable entière n =10

16. Algorithmique et programmation – L1 Stéphane Rivière


– En C++ :

– le nom peut contenir des lettres (y compris ’_’, ! minuscules6=majus-


cules) et des chiffres (mais ne peut pas commencer par un chiffre)
– on peut déclarer plusieurs variables de même type en même temps

type nom; //une variable non initialisée


type nom = valeur; //une variable initialisée
type nom1, nom2; //deux variables non initialisées
type nom1 = valeur1, //deux variables initialisées
nom2 = valeur2;

– exemple :

int var1; //pas terrible comme nom


int var2 = 10; //pas terrible comme nom
double x = 10.2, y = -1.25;
double z;
char choix=’r’;

17. Algorithmique et programmation – L1 Stéphane Rivière


– Une fois déclarée, on peut utiliser une variable :
– Pour lire la valeur stockée dans une variable et l’utiliser : donner le nom de
la variable
– Pour changer la valeur stockée dans une variable : affectation (instruction)

variable = valeur ;
2 ← 1
1. la valeur (une expression) est calculée
2. le résultat est rangé dans la variable
!! ne pas lire la valeur d’une variable non initialisée (c.-à-d. dans laquelle on
n’a pas mis de valeur)
double x = 10.2; int val1 = 10;
double y = -1.25; int val2;
double d; val2 = val1;
d = sqrt(x*x+y*y); val1 = -10;
val2 = val2+1;

18. Algorithmique et programmation – L1 Stéphane Rivière


5.2 Constantes
– Pour utiliser une valeur littérale fixe plusieurs fois dans un programme en
utilisant un nom plutôt que la valeur elle-même : utiliser une constante
– Il faut déclarer la constante avant de l’utiliser (en général après les biblio-
thèques pour pouvoir l’utiliser partout en C++)

– algorithmique : utiliser constante à la place de variable


– C++ : const type nom = valeur;
(déclaration de variable initialisée précédée de const)
– la valeur doit être une valeur connue à l’écriture du programme

– Pour utiliser sa valeur : donner son nom


– On ne peut plus changer sa valeur une fois initialisée

19. Algorithmique et programmation – L1 Stéphane Rivière


– Une constante permet de

– utiliser un nom parlant plutôt qu’une valeur numérique


– changer la valeur numérique à un seul endroit : la déclaration de la
constante

#include<iostream>
#include<cmath>
using namespace std;

const double Pi = 3.1415926535;

int main()
{
cout<<"cos(Pi) = "<<cos(Pi)<<endl;
Pi = 6.14; //Erreur : interdit
cout<<"sin(Pi) = "<<sin(Pi)<<endl;
}

20. Algorithmique et programmation – L1 Stéphane Rivière


6 Entrées/sorties
Bibliothèque iostream

6.1 Affichage de valeurs sur l’écran


– Écran = cout
– On « écrit » une valeur sur l’écran : cout<<valeur ;
– On peut écrire plusieurs valeurs d’un coup : cout<<valeur1<<valeur2
... ;
– Passage à la ligne :
– en forçant tout de suite l’affichage : valeur endl
– sans forçer tout de suite l’affichage : valeur "\n"
double Pi = 3.1415926535;
cout<<"cos(Pi) = "<<cos(Pi)<<"\n";
cout<<"sin(Pi) = "<<sin(Pi)<<endl;

21. Algorithmique et programmation – L1 Stéphane Rivière


6.2 Lecture de valeurs tapées par l’utilisateur au clavier
– « clavier » = cin
– L’utilisateur tape des valeurs au clavier (séparées par des espaces ou des
tabulations)
– Quand l’utilisateur tape sur « entrée », les valeurs tapées sont ajoutées dans
l’ordre dans la mémoire de cin
– On « lit » depuis cin :

– cin>>variable;
– la plus vieille valeur de la mémoire de cin est rangée dans la variable
puis enlevée de cin
– s’il n’y a pas de valeur, le programme attend que l’utilisateur en rentre
une

→ avant de lire une valeur, afficher un message pour prévenir l’utilisateur

22. Algorithmique et programmation – L1 Stéphane Rivière


– On peut lire plusieurs valeurs d’un coup : cin>>variable1>>variable2. . . ;

int n;
cout<<"entrez la dimension : "
cin>>n;
double x,y;
cout<<"entrez x et y : ";
cin>>x>>y;
cout<<"la norme L"<<n<<" vaut : ";
cout<<pow(pow(x,n)+pow(y,n),1.0/n)<<endl;

23. Algorithmique et programmation – L1 Stéphane Rivière


7 Programme complet
#include<iostream> //entrées/sorties
#include<cmath> //fonctions de math
using namespace std;

//ce programme demande une dimension n et deux coordonnées x et y


//et calcule la norme Ln (x^n+y^n)^1/n

int main() //programme principal


{
int n;
cout<<"entrez la dimension : ";
cin>>n;
double x,y;
cout<<"entrez x et y : ";
cin>>x>>y;
cout<<"la norme L"<<n<<" vaut : ";
cout<<pow(pow(fabs(x),n)+pow(fabs(y),n),1.0/n)<<endl;
}

24. Algorithmique et programmation – L1 Stéphane Rivière


7.1 Écrire un programme
– Avant d’écrire un programme en C++, il faut d’abord résoudre le problème
posé :

– modéliser le problème en terme de données :

– quelles sont les données de départ à donner


– quelles sont les données à obtenir en résultat et les affichages à
effectuer en conséquence

– déterminer les actions et les calculs à faire pour obtenir les données
résultats à partir des données de départ
→ algorithme (dans langage algorithmique)

– Une fois l’algorithme trouvé, on le traduit en C++

25. Algorithmique et programmation – L1 Stéphane Rivière


Exemple : calculer un prix TTC
– données de départ : prixHT et taux de la taxe
– données résultat : taxe et prixT T C
– algorithme :

– demander le prixHT (dans prixHT) et le taux de la taxe (dans taux-


Taxe)
– calculer la taxe : taxe = prixHT × taux de la taxe
– calculer le prix TTC : prixT T C = prixHT + taxe
– afficher le résultat

– Traduction en C++

26. Algorithmique et programmation – L1 Stéphane Rivière


#include<iostream>
using namespace std;

//ce programme demande un prix HT, un taux de taxe et


//affiche la taxe et le prix TTC correspondant

int main()
{
//lire le prix HT et le taux de la taxe
double prixHT;
double tauxTaxe;
cout<<"entrez le prix HT et le taux de la taxe : ";
cin>>prixHT>>tauxTaxe;
//calculer la taxe, le prix TTC et les afficher
double taxe = prixHT * tauxTaxe;
double prixTTC = prixHT + taxe;
cout<<"Avec un prix HT de "<<prixHT;
cout<<" et un taux de taxe de "<<tauxTaxe<<"\n";
cout<<"La taxe vaut "<<taxe;
cout<<" et le prix TTC vaut "<<prixTTC<<endl;
}

27. Algorithmique et programmation – L1 Stéphane Rivière


8 Instructions conditionnelles
– On peut exécuter des instructions de façon conditionnelle,
c.-à-d. exécuter ou non des instructions en fonction du résultat d’un test
– Le test lui-même, dont le résultat est vrai ou faux, est donné par une ex-
pression booléenne

8.1 Expressions booléennes


– Une expression booléenne est une expression de type booléen,
c.-à-d. dont le résultat est une valeur booléenne,
c.-à-d. dont le résultat vaut faux ou vrai
– Les valeurs booléennes viennent des :
– valeurs littérales faux et vrai
– résultat des opérateurs de comparaison
– résultats des opérateurs logiques

28. Algorithmique et programmation – L1 Stéphane Rivière


8.1.1 Valeurs littérales booléennes
– Le type booléen est un type qui n’a que deux valeurs : faux et vrai
– En C++ : type bool et valeurs false et true
– On ne peut faire dessus que

– des comparaisons
– des opérations logiques

– On peut éventuellement afficher une valeur booléenne en C++


cout<<boolalpha<<valeur booléenne
– Mais on ne peut pas lire de valeur booléenne au clavier
(lire une valeur et la tester, voir plus loin)

29. Algorithmique et programmation – L1 Stéphane Rivière


8.1.2 Opérateurs de comparaison
– Les opérateurs de comparaison :

– comparent deux valeurs


– renvoient un booléen comme résultat

– Les opérateurs sont en C++ :

== a == b a=b égal à
!= a != b a 6= b différent de
< a < b a<b strictement inférieur à
<= a <= b a≤b inférieur ou égal à
> a > b a>b strictement supérieur à
>= a >= b a≥b supérieur ou égal à

– !!! ne pas confondre le « == » égalité avec le « = » affectation

30. Algorithmique et programmation – L1 Stéphane Rivière


Comparaisons des différents types :

booléen bool false<true


entier int ordre naturel des entiers
réel double ordre naturel des réels
caractères char ordre dans l’encodage utilisé,
en général les lettres et les chiffres sont
dans l’ordre alphabétique
chaînes string ordre lexicographique

31. Algorithmique et programmation – L1 Stéphane Rivière


8.1.3 Opérateurs logiques
– Ils prennent en opérande une ou deux valeurs booléennes
– Ils renvoient en résultat une valeur booléenne suivant la table de vérité
suivante :

a b non a a et b a ou b
Vrai Vrai Faux Vrai Vrai
Vrai Faux Faux Vrai
Faux Vrai Vrai Faux Vrai
Faux Faux Faux Faux

32. Algorithmique et programmation – L1 Stéphane Rivière


– Les opérateurs logiques sont en C++ :

! !a ¬a non a non logique


&& a && b a∧b a et b et logique
|| a || b a∨b a ou b ou logique

– en C++ les opérateurs binaires sont évalués de gauche à droite en court-


circuit :
si après avoir calculé son opérande gauche l’opérateur connaît le résultat
qu’il doit renvoyer, il ne calculera pas son opérande droit

évaluation en court-circuit
a b a et b a ou b
Vrai Vrai a b a
Vrai Faux a b a
Faux Vrai a a b
Faux Faux a a b

33. Algorithmique et programmation – L1 Stéphane Rivière


8.2 Instruction conditionnelle
– Pour exécuter des instructions si une condition est vraie : le si alors

[vrai]
condition

si condition
alors instructions
si vrai [faux]
instructions si condition vraie

1. La condition (une expression booléenne) est calculée


2. si le résultat vaut vrai, alors les instructions du alors sont exécutées

34. Algorithmique et programmation – L1 Stéphane Rivière


– En C++ :

if (condition)
{
//instructions si condition vraie
}

int main()
{
int x;
cout<<"entrez une valeur : ";
cin>>x;
if (x<0)
{
cout<<"x est négatif"<<"\n";
x = -x;
cout<<"et je l’ai rendu positif"<<"\n";
}
cout<<"maintenant x="<<x<<endl;
}

35. Algorithmique et programmation – L1 Stéphane Rivière


– Pour avoir une alternative quand la condition est fausse : le si alors sinon

si condition condition
[vrai] [faux]
alors
instructions si condition vraie instructions instructions
si vrai si faux
sinon
instructions si condition fausse

1. la condition (une expression booléenne) est calculée


2. si le résultat vaut vrai, alors les instructions du alors sont exécutées
sinon (c.-à-d. si le résultat vaut faux) les instructions du sinon sont exécu-
tées

36. Algorithmique et programmation – L1 Stéphane Rivière


– En C++ :

if (condition)
{
//instructions si condition vraie
}
else
{
//instructions si condition fausse
}

– Respecter l’indentation pour la clarté du programme

37. Algorithmique et programmation – L1 Stéphane Rivière


#include<iostream>
using namespace std;

int main()
{
int x;
cout<<"entrez une valeur : ";
cin>>x;
if (x>=0)
{
cout<<"x est positif"<<endl;
}
else
{
cout<<"x est négatif"<<endl;
}
}

38. Algorithmique et programmation – L1 Stéphane Rivière


– Dans les instructions du alors et du sinon on peut de nouveau avoir des si
alors sinon
– Dans le sinon on a des informations : on sait que la condition est fausse
– Dans un si alors sinon, les instructions du alors et du sinon sont liées à
la même condition et sont mutuellement exclusives
– Un si alors sinon n’est pas équivalent à des si successifs :

– on peut recalculer inutilement des conditions dans des si successifs


– les conditions peuvent changer de valeur d’un si à l’autre

39. Algorithmique et programmation – L1 Stéphane Rivière


//échanger la valeur de x entre 1 et 2

//!!! Faux // Juste


if (x==1) if (x==1)
{ {
x=2; x=2;
} }
if (x==2) else
{ {
x=1; x=1;
} }

40. Algorithmique et programmation – L1 Stéphane Rivière


//indiquer position de x par rapport à 0 et 10

//!!! Maladroit
if (x<0)
{ cout<<"x est négatif"<<endl; }
if (x>=0 && x<10)
{ cout<<"x est entre 0 et 10"<<endl; }
if (x>=10)
{ cout<<"x est supérieur à 10"<<endl; }

// Correct

if (x<0)
{
cout<<"x est négatif"<<endl;
}
else //on sait que x>=0
{
if (x<10)
{
cout<<"x est entre 0 et 10"<<endl;
}
else
{
cout<<"x est supérieur à 10"<<endl;
}
}

41. Algorithmique et programmation – L1 Stéphane Rivière


– Quand on fait une serie de tests exclusifs sur la même valeur, c.-à-d. une
série successive de si alors sinon imbriqués
– On peut enlever les accolades des else contenant les if else et aligner
les else if :

if (x<0)
{
cout<<"x est négatif"<<endl;
}
else if (x<10)
{
cout<<"x est entre 0 et 10"<<endl;
}
else
{
cout<<"x est supérieur à 10"<<endl;
}

42. Algorithmique et programmation – L1 Stéphane Rivière


– Pour « lire » une valeur booléenne : lire une valeur et faire un test dessus

bool estUnGarcon;
char reponse;
cout<<"est-vous un (g)arcon ou une (f)ille : ";
cin>>reponse;
if (reponse==’g’)
{
cout<<"vous êtes un garcon"<<endl;
estUnGarcon = true;
}
else
{
cout<<"vous êtes une fille"<<endl;
estUnGarcon = false;
}

//pour ne calculer que estUnGarcon : estUnGarcon = reponse==’g’;

43. Algorithmique et programmation – L1 Stéphane Rivière


9 Instructions itératives
– Une boucle, ou instruction itérative, permet de répéter l’exécution d’instruc-
tions :

– un nombre donné de fois


– en faisant varier un compteur
– tant qu’une condition est vraie

9.1 Boucle « faire n fois »


– Pour répéter l’exécution d’instructions un nombre donné de fois : faire n
fois

faire valeur fois


instructions à répéter

– Les instructions du faire sont exécutées valeur fois

44. Algorithmique et programmation – L1 Stéphane Rivière


– En C++ :

for ( int i=1; i<=valeur; i++ )


{
instructions
}

– Afficher 10 fois « coucou » :

for (int i=1; i<=10; i++)


{
cout<<"coucou"<<endl;
}

45. Algorithmique et programmation – L1 Stéphane Rivière


9.2 Boucle « pour »
– On utilise un compteur que l’on fait varier d’une valeur de départ à une
valeur d’arrivée

pour compteur variant de départ à arrivée [par pas de pas ] faire


instructions à répéter

– Les instructions sont exécutées pour chaque valeur du compteur inférieure


ou égale à la valeur d’arrivée :

– le compteur vaut initialement départ


– il est augmenté de pas (1 par défaut) après chaque exécution des ins-
tructions

– Si départ > arrivée, la boucle n’est pas exécutée


– On peut utiliser (mais pas modifier) la valeur du compteur dans les ins-
tructions

46. Algorithmique et programmation – L1 Stéphane Rivière


– En C++, boucle croissante :
for (int compteur = depart ; compteur <= arrivée ; compteur++ )
{
//instructions à répéter
//on a le droit d’utiliser la valeur du compteur
}

– Le compteur est déclaré et initialisé à la valeur de départ


compteur=départ
– S’il est inférieur à la valeur d’arrivée [faux]
compteur<=arrivée

– les instructions entre accolades sont exécutées [vrai]


instructions
boucle
– le compteur est incrémenté de 1,
compteur++
– on revient au début de la boucle à la comparaison du
compteur avec la valeur d’arrivée

– Si la valeur de départ est supérieure à la valeur d’arrivée, la boucle n’est


pas exécutée

47. Algorithmique et programmation – L1 Stéphane Rivière


– On utilise souvent i, j, ... comme noms de compteurs
– Mais utiliser un nom intelligent si le compteur représente quelque chose
– Le compteur disparaît quand la boucle se termine
– x++ incrémente x de 1
(ou fait passer au caractère suivant si c’est un caractère)
– Coucou « belge » :

int n;
cout<<"nombre d’affichages : ";
cin>>n;
for (int i=1 ; i<=n ; i++)
{
cout<<"coucou "<<i<<" fois"<<endl;
}

48. Algorithmique et programmation – L1 Stéphane Rivière


– La boucle for est de manière générale :

for (déclaration et initialisation compteur ;


condition de continuation sur compteur ;
mise à jour du compteur )
{
//instructions à répéter
}

– Le compteur n’est pas forcément entier (mais cas le plus courant)


– On peut faire des comparaisons strictes dans la condition de continuation

49. Algorithmique et programmation – L1 Stéphane Rivière


– On peut faire diminuer le compteur :
– Attention alors à la condition de continuation
– Pour décrémenter x de 1 : x--
– Compte à rebours :

for (int i=10; i>=0; i--)


{
cout<<i<<endl;
}
cout<<"BOUM !!!"<<endl;

50. Algorithmique et programmation – L1 Stéphane Rivière


– Boucles imbriquées : on peut faire des boucles à
l’intérieur d’une boucle

– pensez juste à bien découper et séparer les


problèmes

– Afficher un rectangle de hauteur lignes de largeur


étoiles :

faire hauteur fois


afficher une ligne de largeur étoiles

– Afficher une ligne de largeur étoiles :

faire largeur fois


afficher une étoile
passer à la ligne

→ Afficher un rectangle de hauteur lignes de largeur


étoiles :

faire hauteur fois


faire largeur fois
afficher une étoile
passer à la ligne

51. Algorithmique et programmation – L1 Stéphane Rivière


– Soit en C++ :

//afficher un rectangle de hauteur lignes de largeur étoiles


void afficherRectangle(int hauteur, int largeur)
{
for (int l=1; l<=hauteur; l++)
{
//afficher une ligne de largeur étoiles
for (int i=1; i<=largeur; i++)
{
cout<<’*’;
}
cout<<endl;
}
}

– Mieux dans les cas compliqués : découper en procédures

52. Algorithmique et programmation – L1 Stéphane Rivière


9.3 Boucle « tant que »
– On veut répéter des instructions tant qu’une condition est vraie

tant que condition faire


instructions à répéter

– La condition du tant que (une expression booléenne) est calculée


– Si elle vaut vrai

– les instructions du tant que sont exécutées


– le programme retourne au début de la boucle, à l’évaluation de la
condition

53. Algorithmique et programmation – L1 Stéphane Rivière


[faux]
– en C++ : boucle while condition
[vrai]
instructions
while (condition) boucle
{
//instructions à répéter
}

– La boucle peut ne pas s’exécuter : quand la condition est fausse dès le


départ
– Les instructions de la boucle doivent modifier les valeurs utilisées dans la
condition pour qu’elle puisse s’arrêter

54. Algorithmique et programmation – L1 Stéphane Rivière


– Exemple, s’assurer qu’une valeur saisie est positive :

– saisir la valeur
– tant que la valeur est négative faire
saisir la valeur

– Soit en C++ :

cout<<"entrez la valeur : ";


cin>>val;
while (val<0)
{
cout<<"rentrez une valeur positive : ";
cin>>val;
}

55. Algorithmique et programmation – L1 Stéphane Rivière


– Faire attention à ce que la boucle puisse s’arrêter

– schéma de Syracuse :

int n; ...
while (n>1)
{
if (n%2==1) //n impair
{
n = 3*n+1;
}
else //n pair
{
n = n/2;
}
}

– s’arrête en pratique, mais ce n’est pas prouvé mathématiquement

56. Algorithmique et programmation – L1 Stéphane Rivière


10 Sous-programmes : fonctions et procédures
– Plutôt que de recopier et modifier du code pour faire plusieurs fois la même
chose sur des valeurs différentes :

– on isole ce code dans des fonctions et procédures où il fait les calculs


avec les valeurs générales passées en paramètre
– on les appelle ensuite quand on en a besoin par leur nom en leur pas-
sant les valeurs à utiliser en argument

– Plutôt que de taper une tonne de code compliqué pour faire quelque chose
de compliqué :

– on découpe le problème en sous-problèmes,


– on résout à part les sous-problèmes dans des fonctions et procédures
séparées
– on les utilise ensuite pour résoudre de façon plus claire à un niveau
d’abstraction plus élevé le problème compliqué

57. Algorithmique et programmation – L1 Stéphane Rivière


10.1 Fonctions
– Exemple : tester si un triangle dont on connaît les coordonnées (x1, y1),
(x2, y2) et (x3, y3) des sommets est équilatéral

– rentrer les coordonnées des trois points


– calculer les longueurs des côtés :
p
longueur12 = (x2 − x1)2 + (y2 − y1)2
p
longueur13 = (x3 − x1)2 + (y3 − y1)2
p
longueur23 = (x3 − x2)2 + (y3 − y2)2
– si les longueurs longueur12, longueur13 et longueur23 sont égales, alors
le triangle est équilatéral
sinon
le triangle n’est pas équilatéral

58. Algorithmique et programmation – L1 Stéphane Rivière


– soit en C++ :

double x1,y1,x2,y2,x3,y3;
cout<<"premier sommet : "; cin>>x1>>y1;
cout<<"deuxième sommet : "; cin>>x2>>y2;
cout<<"troisième sommet : "; cin>>x3>>y3;
double longueur12 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
double longueur13 = sqrt((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1));
double longueur23 = sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
if (longueur12==longueur13 && longueur12==longueur23)
{
cout<<"le triangle est équilatéral"<<endl;
}
else
{
cout<<"le triangle n’est pas équilatéral"<<endl;
}

59. Algorithmique et programmation – L1 Stéphane Rivière


– Plusieurs fois un même calcul peu lisible avec risque d’erreurs dans le co-
pier /coller/modifier
– Il faut tout modifier si on change la formule de calcul
→ Isoler le calcul dans une fonction
– Une fonction :

– a pour but de calculer une valeur et de la renvoyer à l’utilisateur,


– le type de la valeur renvoyée est le type de la fonction
– a un nom pour qu’on puisse l’appeler

– ce nom doit décrire clairement la valeur calculée

60. Algorithmique et programmation – L1 Stéphane Rivière


– Une fonction :

– a des paramètres qui contiendront des valeurs données par l’utilisateur


nécessaires pour faire son calcul
– chaque paramètre a :

– un nom : pour pouvoir l’utiliser dans la fonction


– un type : pour savoir quelle genre de valeur il contient
– le nom du paramètre doit décrire la valeur qu’il contiendra

– renvoie sa valeur avec l’instruction renvoyer

61. Algorithmique et programmation – L1 Stéphane Rivière


– Exemple :

– fonction distance
renvoie un réel
paramètres : x1, y1, x2, y2 : réels, par valeur, coordonnées de deux
points
p
l = (x2 − x1)2 + (y2 − y1)2
renvoyer l

– Soit en C++

double distance(double x1, double y1, double x2, double y2)


{
double d = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
return d;
}

62. Algorithmique et programmation – L1 Stéphane Rivière


– Pour utiliser une fonction :

– on l’appelle par son nom


– en lui donnant les valeurs qu’elle prend en argument pour faire son
calcul :

– Alors :

– chaque valeur donnée en argument à l’appel de la fonction est copiée


dans le paramètre correspondant de la fonction
– le programme exécute le code de la fonction
– lors de l’instruction renvoyer valeur, le programme retourne à l’endroit
où on a appelé la fonction et met cette valeur à la place de la fonction

63. Algorithmique et programmation – L1 Stéphane Rivière


– Tester si un triangle est équilatéral en utilisant la fonction :

– rentrer les coordonnées des trois points


– calculer les longueurs des côtés :
longueur12 = distance(x1, y1, x2, y2)
longueur13 = distance(x1, y1, x3, y3)
longueur23 = distance(x2, y2, x3, y3)
– si les longueurs longueur12, longueur13 et longueur23 sont égales, alors
le triangle est équilatéral
sinon
le triangle n’est pas équilatéral

64. Algorithmique et programmation – L1 Stéphane Rivière


– En C++ :

double x1,y1,x2,y2,x3,y3;
cout<<"premier sommet : "; cin>>x1>>y1;
cout<<"deuxième sommet : "; cin>>x2>>y2;
cout<<"troisième sommet : "; cin>>x3>>y3;
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
double longueur23 = distance(x2,y2,x3,y3);
if (longueur12==longueur13 && longueur12==longueur23)
{
cout<<"le triangle est équilatéral"<<endl;
}
else
{
cout<<"le triangle n’est pas équilatéral"<<endl;
}

65. Algorithmique et programmation – L1 Stéphane Rivière


– Déclaration d’une fonction en C++ :

typeValeurRetour nomFonction(typeParam1 nomParam1, ... )


{
//instructions de la fonction
return valeur_à_renvoyer
}

– Une fonction calcule une valeur et la renvoie


– Pour être sûr de ne pas se tromper :

– déclarer en premier une variable qui va contenir la valeur à calculer


– calculer la valeur dans la variable
– à la fin, renvoyer la valeur de cette variable

– Dans les cas simples on peut renvoyer directement une valeur

66. Algorithmique et programmation – L1 Stéphane Rivière


– Dans certains langages comme C++ l’instruction renvoyer arrête aussitôt
l’exécution de la fonction et renvoie la valeur

– ne pas se servir de cette propriété


– faire en sorte qu’on puisse continuer le calcul

– Quand on écrit une fonction, faire attention à ce

– qu’elle renvoie toujours une valeur


– que le renvoi de la valeur se fasse à la fin d’exécution de la fonction

– Une fonction doit être déclarée avant de pouvoir être utilisée

67. Algorithmique et programmation – L1 Stéphane Rivière


– Fonction qui teste si un triangle est équilatéral :

– valeur de retour : booléen


– nom : triangleEstEquilateral
– paramètres : coordonnées des trois sommets
du triangle

– en C++

//version très détaillée


bool triangleEstEquilateral(
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
bool equilateral; //variable contenant valeur
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
double longueur23 = distance(x2,y2,x3,y3);
if (longueur12==longueur13 &&
longueur12==longueur23)
{
equilateral = true;
}
else
{
equilatéral = false;
}
return equilateral; //renvoyer variable
}

68. Algorithmique et programmation – L1 Stéphane Rivière


//version directe
bool triangleEstEquilateral(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
double longueur23 = distance(x2,y2,x3,y3);
return longueur12==longueur13 && longueur12==longueur23;
}

69. Algorithmique et programmation – L1 Stéphane Rivière


//version intermédiaire
bool triangleEstEquilateral(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
double longueur23 = distance(x2,y2,x3,y3);
if (longueur12==longueur13 && longueur12==longueur23)
{
return true; //fin naturelle de la fonction
}
else
{
return false; //fin naturelle de la fonction
}
}

70. Algorithmique et programmation – L1 Stéphane Rivière


//version fausse
bool triangleEstEquilateral(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
double longueur23 = distance(x2,y2,x3,y3);
if (longueur12==longueur13 && longueur12==longueur23)
{
return true;
}
}

71. Algorithmique et programmation – L1 Stéphane Rivière


//version << algorithmiquement optimisée >> :
bool triangleEstEquilateral(double x1,double y1,
double x2,double y2,
double x3,double y3)
{
bool equilateral;
double longueur12 = distance(x1,y1,x2,y2);
double longueur13 = distance(x1,y1,x3,y3);
if (longueur12 != longueur13)
{
equilateral = false;
}
else
{
double longueur23 = distance(x2,y2,x3,y3);
equilateral = longueur12 == longueur23;
}
return equilateral;
}

72. Algorithmique et programmation – L1 Stéphane Rivière


– Utilisation :

double xt1,yt1,xt2,yt2,xt3,yt3;
cout<<"premier sommet : "; cin>>xt1>>yt1;
cout<<"deuxième sommet : "; cin>>xt2>>yt2;
cout<<"troisième sommet : "; cin>>xt3>>yt3;

if (triangleEstEquilateral(xt1,yt1,xt2,yt2,xt3,yt3))
{
cout<<"le triangle est équilatéral"<<endl;
}
else
{
cout<<"le triangle n’est pas équilatéral"<<endl;
}

73. Algorithmique et programmation – L1 Stéphane Rivière


11 Procédures
11.1 Procédures
– On veut faire plusieurs fois la même chose à plusieurs endroits avec des
valeurs différentes
→ Isoler les instructions que l’on veut exécuter dans une procédure
– Une procédure :

– a un nom pour qu’on puisse l’appeler


– a des paramètres qui contiendront des valeurs données par l’utilisateur
et nécessaires pour exécuter ses instructions
– chaque paramètre a :

– un nom : pour pouvoir l’utiliser dans la procédure


– un type : pour savoir quelle genre de valeur il contient

74. Algorithmique et programmation – L1 Stéphane Rivière


– Procédure pour afficher une personne avec son genre (M. ou Mme)

– procédure afficherPersonne
– paramètres : le nom nom de la personne, chaîne de caractères
et son genre genre, caractère (’f’ pour femme, ’h’ pour homme)
si genre=’f’ afficher Mme sinon afficher M.
afficher nom

– Soit en C++

void afficherPersonne(string nom, char genre)


{
if (genre == ’f’)
{ cout<<"Mme "; }
else
{ cout<<"M. "; }
cout<<nom;
}

75. Algorithmique et programmation – L1 Stéphane Rivière


– Pour utiliser une procédure, on l’appelle en donnant son nom et en argu-
ment les valeurs qu’elle prend pour faire son travail
– Alors :

– chaque valeur donnée à l’appel de la procédure est copiée dans le pa-


ramètre correspondant de la procédure
– le programme exécute le code de la procédure
– à la fin de la procédure, le programme retourne à l’endroit où on a
appelé la procédure et passe à l’instruction suivante

– Un appel de procédure est une instruction


– Une procédure peut être utilisée dans d’autres procédures ou le programme
principal après avoir été déclarée

76. Algorithmique et programmation – L1 Stéphane Rivière


void lettreReduction(string nom, char genre, int reduction)
{
afficherPersonne(nom,genre);
cout<<","<<endl;
cout<<"Veuillez trouver un bon de réduction de "<<reduction<<" %"<<endl;
cout<<"Veuillez ";
afficherPersonne(nom,genre);
cout<<" accepter l’expression de mes sentiments distingués."<<endl;
}

int main()
{
lettreReduction("Dupont",’f’,50);
cout<<endl;
lettreReduction("Dupond",’h’,25);
cout<<endl;
}

77. Algorithmique et programmation – L1 Stéphane Rivière


11.2 Paramètres par référence
– On veut faire une procédure qui modifie ses paramètres

void reinitialiserValeur(int valeur)


{
valeur = -1;
}

int main()
{
int valeurtest = 3;
cout<<valeurtest<<endl; //affiche 3
reinitialiserValeur(valeurtest);
cout<<valeurtest<<endl; //Surprise !!! affiche 3
}

78. Algorithmique et programmation – L1 Stéphane Rivière


– Quand on passe un paramètre par valeur, à l’appel la valeur est copiée dans
le paramètre
→ Seul le paramètre est localement modifié
⇒ Passer le paramètre par référence :

– à l’appel, on passe une variable en paramètre


– le paramètre contient alors la variable
– quand on accède au paramètre, on accède directement à la variable
qu’il contient
→ quand on modifie le paramètre, on modifie la variable qu’il contient

– En C++ : type paramètre& nom paramètre

79. Algorithmique et programmation – L1 Stéphane Rivière


void reinitialiserValeur(int& valeur)
{
valeur = -1;
}

int main()
{
int valeurtest = 3;
cout<<valeurtest<<endl; //affiche 3
reinitialiserValeur(valeurtest);
cout<<valeurtest<<endl; //OK affiche -1
}

– En général : plutôt faire une fonction qui renvoie une valeur qu’une procé-
dure qui modifie un paramètre

80. Algorithmique et programmation – L1 Stéphane Rivière


11.3 Résumé
– Si on calcule une valeur → fonction :
– définir le type de la valeur de retour
– renvoyer cette valeur en fin d’exécution avec return
– Si on fait quelque chose → procédure
– Les paramètres sont les informations que l’utilisateur doit donner à la fonc-
tion/procédure pour qu’elle puisse faire son travail
– si c’est une valeur que l’on donne pour faire les calculs
→ passage par valeur type
– si c’est une variable dans laquelle on veut mettre un résultat à la fin
→ passage par référence type&
– Une fonction ne renvoie qu’une valeur → pour récupérer plusieurs valeurs,
les récupérer comme résultats dans des paramètres par référence d’une
procédure

81. Algorithmique et programmation – L1 Stéphane Rivière


11.4 Décomposition algorithmique procédurale descendante
– Pour résoudre un problème :

– le décomposer en sous-problèmes plus petits


– prendre séparément ces sous-problèmes et les résoudre (en continuant
éventuellement à les découper)

– C’est-à-dire, quand on programme :

– faire comme si les fonctions et procédures qui résolvent ces sous-problèmes


existent et écrire le programme : réfléchir à l’utilisation de ces fonctions
et procédures (nom et paramètres)
– écrire ensuite ces fonctions et procédures

– Rester le plus général possible : penser que les fonctions et procédures


pourraient être utilisées dans d’autres programmes

82. Algorithmique et programmation – L1 Stéphane Rivière


– Exemple, traiter une lettre de réduction pour un client :

– demander les données du client


– afficher la lettre de réduction

– Afficher la lettre de réduction :

– afficher l’en-tête au nom du client


– afficher la réduction personnalisée
– afficher les salutations au nom du client

– Calculer la réduction personnalisée :

– algorithme de calcul à partir de l’âge et du genre

– Dans l’exemple suivant les fonctions et procédures sont écrites dans l’ordre
algorithmique, les mettre par ordre d’utilisation dans le fichier C++

83. Algorithmique et programmation – L1 Stéphane Rivière


void traiterLettre()
{
string nom; char genre, int age;
lireClient(nom,genre,age);
afficherLettre(nom,genre,age);
}

void lireClient(string& nom, char& genre, int& age)


{
cout<<"nom du client : "; cin>>nom;
cout<<"(h)omme ou (f)emme : "; cin>>genre;
cout<<"age : "; cin>>age;
}

void afficherLettre(string nom, char genre, int age)


{
afficherEnTete(nom,genre);
afficherReduction(genre,age);
afficherSalutations(nom,genre);
}

84. Algorithmique et programmation – L1 Stéphane Rivière


void afficherEnTete(string nom, char genre)
{
cout<<"Super magasin de vente"<<endl;
afficherCivilite(nom,genre); cout<<","<<endl;
}

void afficherReduction(char genre, int age)


{
cout<<"Veuillez trouver un bon de réduction de ";
cout<<tauxReduction(genre,age)<<" %"<<endl;
}

int tauxReduction(char genre, int age)


{
int reduction;
if (genre==’f’) { reduction = 50; }
else { reduction = 30; }

if (age>50) { reduction += 10; }


return reduction;
}

85. Algorithmique et programmation – L1 Stéphane Rivière


12 Schémas itératifs
12.1 Calculs itératifs
– On veut calculer une valeur vn définie par récurrence (de proche en proche) :

– on connaît la valeur initiale v0


– on sait calculer la valeur vi à partir de la valeur précédente vi−1
p.ex. par une formule vi = f (vi−1) (dans les cas simples)

– Calculer la valeur de proche en proche :

variable v1 = f (v0)
variable v2 = f (v1)
...
variable vn = f (vn−1)

86. Algorithmique et programmation – L1 Stéphane Rivière


– Mais il faut déclarer n variables :

– pas possible : on ne connait pas n à l’avance


– on ne veut pas garder toutes les valeurs intermédiaires

– Une fois v2 calculé, on n’a plus besoin de v1 ⇒ on peut réutiliser v1 pour


ranger v2 dedans
→ Utiliser une variable v qui va contenir les valeurs successives

variable v = v0 (v contient v0)


v = f (v) (v contient v1)
v = f (v) (v contient v2)
...
v = f (v) (v contient vn)

87. Algorithmique et programmation – L1 Stéphane Rivière


– On répète n fois v = f (v)
→ Utiliser une boucle pour faire ces n mises à jour v = f (v) successives :
variable v = v0
pour i variant de 1 à n faire
v = f (v)
– Soit en C++
v = v0;
for (int i=1; i<=n; i++)
{
v = f(v);
}

– Pour résoudre ce type de problème, il suffit alors de trouver


– la valeur initiale (v0, ou v1)
– la (formule de) mise à jour (f )

88. Algorithmique et programmation – L1 Stéphane Rivière


– D’une manière générale, l’algorithme est :

initialiser v à v0
pour i variant de 1 à n faire

– calculer vi à partir de v (qui contient à ce moment vi−1)


– et ranger le résultat vi dans v (qui contient maintenant vi)

à la fin de la boucle v contient vn

89. Algorithmique et programmation – L1 Stéphane Rivière


– Exemple, calcul de pn = xn :

– valeur initiale : p0 = x0 = 1
– mise à jour : xi = xi−1 × x, soit pi = pi−1 × x

→ Fonction puissance en C++ :

double puissance(double x, int n)


{
double p = 1; //x^0
for (int i=1; i<=n; i++)
{
p = p*x;
}
return p;
}

90. Algorithmique et programmation – L1 Stéphane Rivière


Pn
– Calcul de la somme des puissances SommePn = 0 xi :
– valeur initiale : SommeP0 = x0 = 1
– mise à jour : SommePi = SommePi−1 + xi
→ Fonction somme puissances en C++ :

double sommePuissances(double x, int n)


{
double sommeP = 1; //x^0
for (int i=1; i<=n; i++)
{
sommeP = sommeP + puissance(x,i);
}
return sommeP;
}

– Inconvénient de la méthode : à chaque appel de puissance(x,i) le


calcul de xi est refait entièrement, soit i multiplications,
soit au total n(n − 1)/2 multiplications

91. Algorithmique et programmation – L1 Stéphane Rivière


– Un calcul peut faire intervenir plusieurs calculs itératifs en parallèle
– Étudier les valeurs initiales et les mises à jour de chaque calcul
– Et utiliser une variable pour chaque valeur
– Mettre ces variables à jour en parallèle dans la même boucle
Pn i n
Pn i
– Exemple : pour calculer 0 x , on calcule pn = x et SommePn = 0 x en
parallèle :

– valeurs initiales :

– p0 = x0 = 1
– SommeP0 = p0

– mises à jour :

– pi = pi−1 × x
– SommePi = SommePi−1 + pi

92. Algorithmique et programmation – L1 Stéphane Rivière


→ Soit en C++ :

double sommePuissances(double x, int n)


{
double p = 1; //x^0
double sommeP = p;
for (int i=1; i<=n; i++)
{
p = p * x;
sommeP = sommeP + p;
}
return sommeP;
}

93. Algorithmique et programmation – L1 Stéphane Rivière


12.2 Calculs avec condition d’arrêt
– On ne connaît pas à l’avance le n du vn à calculer
– Mais on veut calculer le premier vi qui vérifie une condition C
→ Même principe en utilisant une boucle tant que à la place de la boucle
pour :

initialiser v à v0
tant que v ne vérifie pas C faire

– calculer vi à partir de v (qui contient à ce moment vi−1)


– et ranger le résultat vi dans v (qui contient maintenant vi)

à la fin de la boucle v contient le premier vi vérifiant C

94. Algorithmique et programmation – L1 Stéphane Rivière


– Calcul de la racine carrée entière d’un réel x : le plus grand entier r tel que
r2 ≤ x
→ Trouver le premier entier r tel que r2 > x, et la racine est r − 1
– valeur initiale : r0 = 1
– mise à jour : ri = ri−1 + 1
– condition de continuation : ri2 ≤ x
– Soit en C++ :
int racineEntiere(double x)
{
int r = 1;
while (r*r<=x)
{
r = r+1;
}
return r-1;
}

95. Algorithmique et programmation – L1 Stéphane Rivière


– Le calcul peut faire intervenir des valeurs consécutives :

– garder chacune de ces valeurs en mémoire dans sa variable


– dans la mise à jour : ne calculer que la nouvelle valeur,
les anciennes (à copier) deviennent les nouvelles des rangs inférieurs

– Calcul de a : limite de la suite xn où

– x0 = racine entière de x
1 a
– xn = (xn−1 + )
2 xn−1

– On veut arrêter le calcul quand deux termes consécutifs sont égaux à ε


près
→ Garder en mémoire deux termes consécutifs

96. Algorithmique et programmation – L1 Stéphane Rivière


double racineCarreeNewton(double a, double eps)
{
double x0 = racineEntiere(a);
double x1 = 0.5*(x0+a/x0);
while (fabs(x1-x0)>eps)
{
x0 = x1; //ne pas recalculer le nouveau x0 : c’est l’ancien x1
x1 = 0.5*(x0+a/x0);
}
return x1;
}

97. Algorithmique et programmation – L1 Stéphane Rivière


13 Structures
– On veut faire une bibliothèque de fonctions et procédures pour manipuler
des points
– Un point est représenté par ses coordonnées x et y
– Afficher un point sous la forme (x, y) :
void afficherPoint(double x, double y)
{
cout<<’(’<<x<<’,’<<y<<’)’;
}

– Lire les données d’un point sous la forme (x, y) :


void lirePoint(double& x, double& y)
{
char c;
cin>>c>>x>>c>>y>>c;
}

98. Algorithmique et programmation – L1 Stéphane Rivière


– Test :

void testESPoint()
{
double xtest,ytest;
cout<<"entrez un point : ";
lirePoint(xtest,ytest);
cout<<"le point entré est : ";
afficherPoint(xtest,ytest);
cout<<endl;
}

int main()
{
testESPoint();
}

99. Algorithmique et programmation – L1 Stéphane Rivière


– Un point est représenté par plusieurs données
– Plutôt que de gérer séparément ces données : les regrouper ensemble dans
un même endroit
– Utiliser un nouveau type de données : un type structure, type « boîte à
variables » qui permet de regrouper ensemble plusieurs variables
– Déclarer d’abord un type structure en dehors des fonctions et procédures :
struct nom du type
{
déclaration des variables contenues
};

– par exemple :
struct point
{
double x,y;
};

100. Algorithmique et programmation – L1 Stéphane Rivière


– On déclare des variables de type structure comme pour les autres types :
point p;
– Une variable de type structure contient des variables correspondant à celles
déclarées dans le type
– Chaque variable de type structure contient ses variables à elles
– On accède à ces variables avec « . » :
variable structure.variable contenue
– Par exemple, les coordonnées d’un point p sont p.x et p.y

point p;
cout<<"entrez les coordonnées du point : ";
cin>>p.x>>p.y;
cout<<"vous avez entré x="<<p.x<<" y="<<p.y<<endl;

101. Algorithmique et programmation – L1 Stéphane Rivière


– On peut initialiser les variables contenues dans une structure en donnant
à la déclaration leurs valeurs dans l’ordre entre accolades séparées par des
virgules
– Mais on ne peut pas copier de cette façon des valeurs dans une variable
structure

point p1 = { 1.1, -2.2 }; //initialisation : p1.x=1.1 et p1.y=-2.2


point p2 = { -2.1, 3.1 }; //initialisation : p2.x=-2.1 et p2.y=3.2

x 1.1 x -2.1
p1 p2
y -2.2 y 3.1

p1 = { 3.1, -4.7 }; //Erreur ! affectation interdite

102. Algorithmique et programmation – L1 Stéphane Rivière


– À part la copier et utiliser les variables contenues dans une structure, on
ne peut rien faire directement sur une structure

point p1,p2;
cin>>p1.x>>p1.y; //cin>>p1 : erreur
p2 = p1;

– On peut passer des structures en paramètre

– par « valeur » (donnée) : const nom type structure& p,


– par référence (résultat) : nom type structure& p

→ Passer des points en paramètre :

– par « valeur » : const point& p,


– par référence : point& p

103. Algorithmique et programmation – L1 Stéphane Rivière


void afficherPoint(const point& p) //affiche sous la forme (x,y)
{
cout<<’(’<<p.x<<’,’<<p.y<<’)’;
}

void lirePoint(point& p) //lit sous la forme (x,y)


{
char c;
cin>>c>>p.x>>c>>p.y>>c;
}

void testESPoint2()
{
point ptest;
cout<<"entrez un point : ";
lirePoint(ptest);
cout<<"le point entre est : ";
afficherPoint(ptest);
cout<<endl;
}

104. Algorithmique et programmation – L1 Stéphane Rivière


– Chaque point a bien son x et son y à lui
– Il est plus facile d’utiliser plusieurs points

double distance(const point& p1, const point& p2)


{
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
return sqrt(dx*dx + dy*dy);
}

point p1 = { 1.2, -3.2 };


point p2 = { -4, 3.7 };
afficherPoint(p1); //affiche (1.2,-3.2)
afficherPoint(p2); //affiche (-4,3.7)
cout<<"p1p2 = "<<distance(p1, p2);

105. Algorithmique et programmation – L1 Stéphane Rivière


– Une structure peut contenir

– un nombre quelconque de variables


– de types quelconques différents

struct personne {
string nom;
int age;
double poids;
};

void affichePersonne(const personne& p)


{
cout<<"la personne "<<p.nom<<" a "<<p.age<<" ans";
cout<<" et pèse "<<p.poids<<" kg";
}

personne p = { "Martin", 42, 71.2 };


affichePersonne(p);

106. Algorithmique et programmation – L1 Stéphane Rivière


– Une structure peut contenir d’autres structures
– Comme pour les poupées russes : ouvrir les boîtes avec « . » jusqu’à la
variable voulue
struct triangle {
point p1, p2, p3;
};

double perimetre(const triangle& t)


{
return distance(t.p1,t.p2) + distance(t.p2,t.p3) + distance(t.p3,t.p1);
}

//si distance(x1,y1,x2,y2) existe à la place de distance(p1,p2)


double perimetre(const triangle& t)
{
return distance(t.p1.x, t.p1.y ,t.p2.x, t.p2.y)
+ distance(t.p2.x, t.p2.y ,t.p3.x, t.p3.y)
+ distance(t.p3.x, t.p1.y ,t.p1.x, t.p1.y);
}

107. Algorithmique et programmation – L1 Stéphane Rivière


14 Les tableaux
14.1 Introduction
– On veut pouvoir manipuler des variables numérotées grâce à leur numéro
– Par exemple stocker des mesures d’enneigement mi pour faire des statis-
tiques :

– saisir les valeurs :

– demander le nombre n de valeurs


– demander les valeurs mi pour i = 1 à n

– ré-afficher correctement les valeurs :

– afficher mi pour i = 1 à n
n
X mi
– calculer la moyenne : m̄ =
1
n

108. Algorithmique et programmation – L1 Stéphane Rivière


– Problème : il faut déclarer et manipuler toutes les variables une à une :

– variables m1, m2, . . . m100


– demander m1, demander m2, . . . demander m100
– afficher m1, afficher m2, . . . afficher m100
– moyenne=(m1+m2+ . . . +m100)/100

– Soit en C++ :

//les ... n’existent pas, ils doivent être complétés à la main !!


double m1, m2, ..., m100;
//on écrirait double mun, mdeux ...; ça serait pareil
cout<<"valeur 1 : "; cin>>m1; ... cout<<"valeur 100 : ";cin>>m100;
cout<<m1<<’ ’<<m2<<’ ’<< ... <<’ ’<<m100<<endl;
double moyenne=(m1+m2+...m100)/100;
cout<<"moyenne = "<<moyenne<<endl;

– Impossible concrètement à gérer et à faire varier le nombre de variables

109. Algorithmique et programmation – L1 Stéphane Rivière


→ Utiliser un tableau

– un tableau est un « casier » à variables de même type rangées consécu-


tivement en mémoire
→ chaque variable d’un tableau t est numérotée et accessible par son
numéro (calculable) : t[i]

variables séparées t5 t1
t3
rangées n'importe où
t2 t4

tableau = variables t
rangées et numérotées
t[0] t[1] t[2] t[3] t[4]
→ on peut écrire des algorithmes avec ti où i est un numéro que l’on peut
faire varier
– la taille d’un tableau est son nombre de cases

110. Algorithmique et programmation – L1 Stéphane Rivière


14.2 Tableaux statiques à une dimension
– Un tableau statique est un tableau de taille fixe donnée à l’écriture du
programme
– Mais on n’est pas obligé d’utiliser toutes ses cases :

– on peut n’utiliser que les n premières cases


– sa taille réelle étant sa taille maximale

– Il est préférable de déclarer cette taille maximale en constante


– On peut directement déclarer des variables/paramètres de type tableau
(voir à la fin)
– Si on utilise plusieurs fois le même type de tableau :

– il est préférable de déclarer un type tableau


– cela facilite la déclaration des variables/paramètres

111. Algorithmique et programmation – L1 Stéphane Rivière


– On veut au plus 366 mesures réelles d’enneigement
– Taille maximale du tableau :

const int NBMESURESMAX = 366;

– Déclarer un type tableau :

– en C++ : using mesures = array<double,NBMESURESMAX>;


(inclure alors la bibliothèque <array>)
– à l’ancienne : using mesures = double[NBMESURESMAX];
– à l’ancienne façon C : typedef double mesures[NBMESURESMAX];

– Déclarer des variables de type tableau : mesures m;


– m contient NBMESURESMAX variables numérotées à partir de 0 accessibles
par leur numéro : m[numéro] (c.-à-d. m contient m[0], m[1], . . . )

112. Algorithmique et programmation – L1 Stéphane Rivière


– Le numéro est une expression entière dont la valeur doit être comprise
entre 0 et NBMESURESMAX − 1
→ Utiliser une boucle et son compteur pour parcourir les numéros de case
voulus du tableau
– m[numéro] est une variable de type réel, qui s’utilise comme toutes les
autres variables
– On ne peut pas directement afficher, lire, additionner . . . un tableau t
– Il faut le faire individuellement pour chaque case du tableau
– On a le droit de copier des tableaux définis avec array : copie alors tout
le tableau
– !!! Si on utilise les n premières cases, elles sont numérotées de 0 à n − 1
0 1 i n-1 n
t

113. Algorithmique et programmation – L1 Stéphane Rivière


– Saisie, affichage et calcul de la moyenne des mesures d’enneigement :
#include<iostream>
#include<array>
using namespace std;

const int NBMESURESMAX = 366;


using mesures = array<double, NBMESURESMAX>;
//ou : using mesures = double[NBMESURESMAX];

void programme()
{
mesures m;
int n;
cout<<"nombre de mesures : ";
cin>>n;
while (n>NBMESURESMAX)
{
cout<<"nombre de mesures : ";
cin>>n;
}

114. Algorithmique et programmation – L1 Stéphane Rivière


cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<n; i++) //cin>>m : interdit
{
cout<<"mesure "<<i<<" : ";
cin>>m[i];
}
cout<<"valeurs rentrées : ";
for (int i=0; i<n; i++) //cout<<m : interdit
{
cout<<m[i]<<’ ’;
}
cout<<endl;
double somme = 0.0;
for (int i=0; i<n; i++)
{
somme = somme + m[i];
}
double moyenne = somme/n;
cout<<"la moyenne des mesures est : "<<moyenne<<endl;
}

115. Algorithmique et programmation – L1 Stéphane Rivière


– On peut passer un tableau en paramètre d’une fonction ou d’une procé-
dure :

– passage en donnée (par « valeur ») :

– const mesure& m

– passage en résultat (par référence) :

– mesure& m

– Remarque : le & est facultatif si on n’utilise pas array (on perd alors
l’information sur la taille maximale du tableau)

116. Algorithmique et programmation – L1 Stéphane Rivière


– Saisie, affichage et calcul de la moyenne des mesures d’enneigement :

const int NBMESURESMAX = 366;


using mesures = array<double, NBMESURESMAX>;
//ou : using mesures = double[NBMESURESMAX];

void saisirMesures(mesures& m, int& n)


{
cout<<"nombre de mesures : "; cin>>n;
while (n>NBMESURESMAX)
{ cout<<"nombre de mesures : "; cin>>n; }
cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<n; i++)
{
cout<<"mesure "<<i<<" : ";
cin>>m[i];
}
}

117. Algorithmique et programmation – L1 Stéphane Rivière


void afficherMesures(const mesures& m, int n)
{
cout<<"valeurs rentrées : ";
for (int i=0; i<n; i++)
{
cout<<m[i]<<’ ’;
}
cout<<endl;
}

double moyenne(const mesures& m, int n)


{
double somme = 0.0;
for (int i=0; i<n; i++)
{
somme = somme + m[i];
}
return somme/n;
}

void programme()
{
mesures mes;
int n;
saisirMesures(mes,n);
afficherMesures(mes,n);
cout<<"moyenne : "<<moyenne(mes,n)<<endl;
}

118. Algorithmique et programmation – L1 Stéphane Rivière


14.2.1 Résumé
– Déclarer un type tableau typeTableau de NMAX cases de type typecases :
– en C++ : using typeTableau = array<typecases,NMAX>;
– à l’ancienne : using typeTableau = typecases[NMAX];
– Déclarer une variable tableau t : typeTableau t;
– Passer un tableau en paramètre :
– en donnée (par valeur) : const typeTableau& t
– en résultat (par référence) : typeTableau& t
– Utiliser un tableau : utiliser ses cases, numérotées à partir de 0
– t[numéro] est une variable de type typecases
– Le numéro de case doit être dans [0, n[, où n est le nombre de cases
utilisées (n ≤ NMax)
→ toujours connaître le nombre de cases que l’on utilise

119. Algorithmique et programmation – L1 Stéphane Rivière


14.3 Utilisation directe de tableaux C++
– On peut ponctuellement utiliser directement un tableau sans déclarer de
type

14.3.1 Tableau C++ array


– variable : array<typecases,NMAX> t;
– paramètre en donnée : const array<typecases,NMAX>& t
– paramètre en résultat : array<typecases,NMAX>& t

void print(const array<int,30>& t)


{
for (int i=0;i<30;i++) { cout<<t[i]<<’ ’; }
}

array<int,30> t;
print(t);

120. Algorithmique et programmation – L1 Stéphane Rivière


14.3.2 Tableau à l’ancienne
– variable : typecases t[NMAX];
– paramètre en donnée : const typecases t[]
– paramètre en résultat : typecases t[]

void print(const int t[])


{
for (int i=0;i<30;i++) { cout<<t[i]<<’ ’; }
}

int t[30];
print(t);

121. Algorithmique et programmation – L1 Stéphane Rivière


14.4 Ranger un tableau dans une structure
– Un tableau est inutilisable sans sa taille
– Plutôt que d’avoir un tableau et sa taille dans des variables séparées : les
regrouper dans une structure

const int NBMESURESMAX=366;

using tableauMesures = array<double,NBMESURESMAX>;


//ou using tableauMesures = array[NBMESURESMAX];

struct mesures
{
tableauMesures m;
int n;
};

122. Algorithmique et programmation – L1 Stéphane Rivière


void saisirMesures(mesures& mes)
{
cout<<"nombre de mesures : ";
cin>>mes.n;
while (mes.n>NBMESURESMAX)
{ cout<<"nombre de mesures : "; cin>>mes.n; }
cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<mes.n; i++)
{
cout<<"mesure "<<i<<" : "; cin>>mes.m[i];
}
}
void afficherMesures(const mesures& mes)
{
cout<<"valeurs rentrées : ";
for (int i=0; i<mes.n; i++)
{
cout<<mes.m[i]<<’ ’;
}
cout<<endl;
}

123. Algorithmique et programmation – L1 Stéphane Rivière


double moyenne(const mesures& mes)
{
double somme = 0.0;
for (int i=0; i<mes.n; i++)
{
somme = somme + mes.m[i];
}
return somme/mes.n;
}

void programme()
{
mesures mes;
saisirMesures(mes)
afficherMesures(mes)
cout<<"la moyenne des mesures est : "<<moyenne(mes)<<endl;
}

124. Algorithmique et programmation – L1 Stéphane Rivière


15 Les tableaux
15.1 Introduction
– On veut pouvoir manipuler des variables numérotées grâce à leur numéro
– Par exemple stocker des mesures d’enneigement mi pour faire des statis-
tiques :

– saisir les valeurs :

– demander le nombre n de valeurs


– demander les valeurs mi pour i = 1 à n

– ré-afficher correctement les valeurs :

– afficher mi pour i = 1 à n
n
X mi
– calculer la moyenne : m̄ =
1
n

125. Algorithmique et programmation – L1 Stéphane Rivière


– Problème : il faut déclarer et manipuler toutes les variables une à une :

– variables m1, m2, . . . m100


– demander m1, demander m2, . . . demander m100
– afficher m1, afficher m2, . . . afficher m100
– moyenne=(m1+m2+ . . . +m100)/100

– Soit en C++ :

//les ... n’existent pas, ils doivent être complétés à la main !!


double m1, m2, ..., m100;
//on écrirait double mun, mdeux ...; ça serait pareil
cout<<"valeur 1 : "; cin>>m1; ... cout<<"valeur 100 : ";cin>>m100;
cout<<m1<<’ ’<<m2<<’ ’<< ... <<’ ’<<m100<<endl;
double moyenne=(m1+m2+...m100)/100;
cout<<"moyenne = "<<moyenne<<endl;

– Impossible concrètement à gérer et à faire varier le nombre de variables

126. Algorithmique et programmation – L1 Stéphane Rivière


→ Utiliser un tableau

– un tableau est un « casier » à variables de même type rangées consécu-


tivement en mémoire
→ chaque variable d’un tableau t est numérotée et accessible par son
numéro (calculable) : t[i]

variables séparées t5 t1
t3
rangées n'importe où
t2 t4

tableau = variables t
rangées et numérotées
t[0] t[1] t[2] t[3] t[4]
→ on peut écrire des algorithmes avec ti où i est un numéro que l’on peut
faire varier
– la taille d’un tableau est son nombre de cases

127. Algorithmique et programmation – L1 Stéphane Rivière


15.2 Tableaux dynamiques à une dimension
– Un tableau dynamique est un tableau :

– dont la taille initiale peut être donnée à l’exécution du programme


– dont on peut faire varier la taille en cours d’exécution

– Si on utilise plusieurs fois le même type de tableau :

– il est préférable de déclarer un type tableau


– cela facilite la déclaration des variables/paramètres

– Tableau dynamique en C++ :

– bibliothèque <vector>
– type vector

128. Algorithmique et programmation – L1 Stéphane Rivière


– Déclarer un type tableau :
using mesures = vector<double>;
– Déclarer des variables de type tableau :
mesures m(n);
– m contient n variables numérotées à partir de 0 accessibles par leur nu-
méro : m[numéro] (c.-à-d. m contient m[0], m[1], . . . )
– !!! Les n cases d’un tableau sont numérotées de 0 à n − 1
– On peut demander la taille du tableau au tableau : la taille du tableau t
est t.size()
0 1 i n-1 n =
t.size()
t

– Les cases valent 0 par défaut, pour qu’elles valent une valeur :
mesures m(n, valeur);

129. Algorithmique et programmation – L1 Stéphane Rivière


– Utiliser une boucle et son compteur pour parcourir les numéros de case
voulus du tableau
– m[numéro] est une variable de type réel, qui s’utilise comme toutes les
autres variables
– On ne peut pas directement afficher, lire, additionner . . . un tableau t
– Il faut le faire individuellement pour chaque case du tableau
– On a le droit de copier des tableaux dynamiques

130. Algorithmique et programmation – L1 Stéphane Rivière


– Saisie, affichage et calcul de la moyenne des mesures d’enneigement :

#include<iostream>
#include<vector>
using namespace std;

using mesures = vector<double>;

void programme()
{
int n;
cout<<"nombre de mesures : ";
cin>>n;
mesures m(n);

131. Algorithmique et programmation – L1 Stéphane Rivière


cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<m.size(); i++) //cin>>m : interdit
{
cout<<"mesure "<<i<<" : ";
cin>>m[i];
}
cout<<"valeurs rentrées : ";
for (int i=0; i<m.size(); i++) //cout<<m : interdit
{
cout<<m[i]<<’ ’;
}
cout<<endl;
double somme = 0.0;
for (int i=0; i<m.size(); i++)
{
somme = somme + m[i];
}
double moyenne = somme/m.size();
cout<<"la moyenne des mesures est : "<<moyenne<<endl;
}

132. Algorithmique et programmation – L1 Stéphane Rivière


– On peut passer un tableau en paramètre d’une fonction ou d’une procé-
dure :

– passage en donnée (par « valeur ») :

– const mesure& m

– passage en résultat (par référence) :

– mesure& m

– On peut aussi écrire des fonctions qui créent et renvoient un tableau


(à préférer en général à modifier un tableau en résultat)

– valeur de retour : mesures

133. Algorithmique et programmation – L1 Stéphane Rivière


– Saisie, affichage et calcul de la moyenne des mesures d’enneigement :

using mesures = vector<double>;

mesures mesuresSaisies()
{
int n;
cout<<"nombre de mesures : ";
cin>>n;
mesures m(n);
cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<m.size(); i++)
{
cout<<"mesure "<<i<<" : ";
cin>>m[i];
}
return m;
}

134. Algorithmique et programmation – L1 Stéphane Rivière


void afficherMesures(const mesures& m)
{
cout<<"valeurs rentrées : ";
for (int i=0; i<m.size(); i++)
{
cout<<m[i]<<’ ’;
}
cout<<endl;
}

double moyenne(const mesures& m)


{
double somme = 0.0;
for (int i=0; i<m.size(); i++)
{
somme = somme + m[i];
}
return somme/m.size();
}

void programme()
{
mesures mes = mesuresSaisies();
afficherMesures(mes);
cout<<"moyenne : "<<moyenne(mes)<<endl;
}

135. Algorithmique et programmation – L1 Stéphane Rivière


15.2.1 Résumé
– Déclarer un type tableau typeTableau dynamique de cases de type type-
cases :

– using typeTableau = vector<typecases>;

– Déclarer une variable tableau t de taille cases : typeTableau t(taille);


– Passer un tableau en paramètre :

– en donnée (par valeur) : const typeTableau& t


– en résultat (par référence) : typeTableau& t

– On peut renvoyer un tableau comme valeur d’une fonction


– Utiliser un tableau : utiliser ses cases, numérotées à partir de 0

– t[numéro] est une variable de type typecases


– Le numéro de case doit être dans [0, t.size()[

136. Algorithmique et programmation – L1 Stéphane Rivière


15.3 Utilisation directe de tableaux dynamiques
– On peut ponctuellement utiliser directement un tableau sans déclarer de
type
– variable : vector<typecases> t(taille);
– paramètre en donnée : const vector<typecases>& t
– paramètre en résultat : vector<typecases>& t
– valeur de retour d’une fonction : vector<typecases>

void print(const vector<int>& t)


{
for (int i=0;i<t.size();i++) { cout<<t[i]<<’ ’; }
}

vector<int> t;
print(t);

137. Algorithmique et programmation – L1 Stéphane Rivière


15.4 Changer la taille d’un tableau
– Quand on déclare un tableau, il est créé avec une certaine taille :

– vector<double> t(taille); : tableau de taille cases valant 0


– vector<double> t(taille, valeur); : tableau de taille cases
valant valeur
– vector<double> t; : tableau vide (c.-à-d. de 0 case)

– Cette taille pourra ensuite changer :

– connaître la taille d’un tableau : t.size()


– savoir si un tableau est vide : t.empty() (renvoie vrai si t est vide,
faux sinon)

138. Algorithmique et programmation – L1 Stéphane Rivière


– On peut changer la taille d’un tableau dynamique en cours de route en :

– changeant la taille : r.resize(nouvelleTaille);


(si la taille est plus petite, les valeurs en trop sont perdues)
– ajoutant un élément en fin de tableau : t.push_back(valeur);
(la taille augmente donc de 1)
– enlevant le dernier élément du tableau : t.pop_back();
(la taille diminue donc de 1)
– vidant le tableau : t.clear();
(la taille devient 0)

139. Algorithmique et programmation – L1 Stéphane Rivière


– On peut créer un tableau en ajoutant les valeurs au fur et à mesure
(dans ce cas, si on connaît à l’avance la taille finale, la pré-réserver avec
t.reserve(tailleFinale))
mesures mesuresSaisies()
{
int n;
cout<<"nombre de mesures : "; cin>>n;
mesures m;
m.reserve(n); //m toujours vide, mais place réservée pour plus tard
cout<<"rentrez les mesures : "<<endl;
for (int i=0; i<n; i++)
{
double mes;
cout<<"mesure "<<i<<" : ";
cin>>mes;
m.push_back(mes)
}
return m;
}

140. Algorithmique et programmation – L1 Stéphane Rivière


16 Recherches linéaires
16.1 Chercher si un élément est présent
– On veut savoir si un élément est présent dans une ensemble d’éléments
– C.-à-d. étant donnée une valeur, calculer present valant vrai si un des
éléments vaut cette valeur, faux sinon
→ Calculer avec un schéma itératif :

– present = faux (pour l’instant on n’a pas vu la valeur)


– pour chaque élément e de l’ensemble

– si e = valeur
– present = vrai

141. Algorithmique et programmation – L1 Stéphane Rivière


– Soit avec un tableau par exemple :

bool contientValeur(const tableau& t, int valeur)


{
//si t structure avec tableau, utiliser t.taille et t.c[i] p.ex.
bool present = false;
for (int i=0; i<t.size(); i++)
{
if (t[i] == valeur)
{
present = true;
}
}
return present;
}

– Inconvénient de la méthode : on continue à tester les éléments de l’en-


semble même après avoir vu un élément valant la valeur

142. Algorithmique et programmation – L1 Stéphane Rivière


– On veut arrêter la recherche si on trouve la valeur en cours de route
– Mais il faut faire attention à ne pas sortir de l’ensemble des éléments si
aucun ne vaut la valeur
1. Transformer la boucle pour en boucle tant que :

– present = faux (pour l’instant on n’a pas vu la valeur)


– i = position du premier élément
– tant que i est dans l’ensemble

– si ei = valeur
– present = vrai
– i = position suivante

143. Algorithmique et programmation – L1 Stéphane Rivière


2. Pour maintenant arrêter la boucle quand on tombe sur la valeur :

– tester en plus present dans la boucle tant que


– passer à la position suivante si on est pas sur la valeur

– i = position du premier élément


– tant que i est dans l’ensemble et pas present

– si ei = valeur
– present = vrai
– sinon
– i = position suivante

– l’ordre de la condition dans la boucle est important

– tester en premier qu’on est bien dans le tableau


– avant de tester l’élément correspondant

144. Algorithmique et programmation – L1 Stéphane Rivière


bool contientValeur(const tableau& t, int valeur)
{
bool present = false;
int i = 0;
while (i<t.size() && !present)
{
if (t[i] == valeur)
{
present = true
}
else
{
i++;
}
}
return present;
}

145. Algorithmique et programmation – L1 Stéphane Rivière


– Ici tester si l’élément vaut la valeur est simple et peut être mis dans la
boucle while à la place de present :

– i = position du premier élément


– tant que i est dans l’ensemble et pas ei = valeur

– i = position suivante

– Comment à la fin de la boucle savoir maintenant si un élément valant


valeur était présent : tester où la boucle s’est arrêtée

– si i est dans l’ensemble : la boucle s’est arrêtée parce qu’on est sur un
élément ei = valeur → la valeur est présente
– si i est hors de l’ensemble : la boucle a parcouru tous les éléments
qui ne valaient pas valeur et s’est arrêtée parce qu’on est sorti de l’en-
semble

– Autrement dit : trouve = vrai ⇐⇒ i est dans l’ensemble

146. Algorithmique et programmation – L1 Stéphane Rivière


bool contientValeur(const tableau& t, int valeur)
{
int i = 0;
while (i<t.size() && !(t[i] == valeur)) //ou && t[i] != valeur
i++;
}
if (i<t.size()) //on s’est arrêté dans l’ensemble
{
return true;
}
else //on a parcouru tout l’ensemble sans trouver
{
return false;
}
//ou plus concis : return i<t.size();
}

147. Algorithmique et programmation – L1 Stéphane Rivière


– On veut maintenant savoir si aucun élément ne vaut la valeur : calculer
vrai si aucun élément ne vaut la valeur, faux sinon
– Il faut en fait trouver s’il existe un élément qui vaut la valeur :

– s’il existe, la réponse est faux


– s’il n’existe pas la réponse est vraie

– C’est le même algorithme que précédemment, seule la conclusion change

bool neContientPasValeur(const tableau& t, int valeur)


{
int i = 0;
while (i<t.size() && !(t[i] == valeur)) //ou && t[i] != valeur
i++;
}
return i == t.size();
}

148. Algorithmique et programmation – L1 Stéphane Rivière


17 Algorithmes basés sur une recherche linéaire
– On veut calculer une valeur booléenne sur un ensemble d’éléments dépen-
dant de la présence d’un élément vérifiant une propriété donnée :

– déterminer la propriété cherchée (qui fait que quand l’on trouve un


élément la vérifiant, on a la réponse au problème)
– déterminer si la réponse est vrai ou faux quand on trouve la réponse

– On peut alors utiliser une recherche linéaire :

– chercher un élément vérifiant la propriété en s’arrêtant dès qu’on en


trouve un
– regarder si on l’a trouvé et conclure

149. Algorithmique et programmation – L1 Stéphane Rivière


→ Algorithme :

– se placer au premier élément


– tant que il reste des éléments et
l’élément courant ne vérifie pas la propriété

– passer à l’élément suivant

– s’il reste des éléments

– c’est qu’on a trouvé un élément vérifiant la propriété → conclure

– sinon

– c’est qu’on n’a pas trouvé d’élément vérifiant la propriété → conclure

150. Algorithmique et programmation – L1 Stéphane Rivière


– Soit en C++ si les valeurs sont rangées dans un tableau par exemple

int i = 0; //premier élément


while (i<v.size() && v[i] ne vérifie pas la propriété)
{
i++; //passer à l’élément suivant
}
if (i<v.size()) //on s’est arrêté en cours de route
{ //on a trouvé un élément vérifiant la propriété : conclure }
else //on vient de sortir du tableau
{ //on n’a pas trouvé d’élément vérifiant la propriété : conclure }

151. Algorithmique et programmation – L1 Stéphane Rivière


– Exemple : est-ce que tous les éléments sont nuls ?

– propriété cherchée : un élément ne valant pas zéro


– résultat : si on en trouve un la réponse est non, sinon la réponse est
oui

bool estNul(const tableau& t)


{
int i = 0;
while (i<t.size() && !(t[i]!=0)) //ou && t[i]==0.0
{
i++;
}
if (i<v.size()) //on a trouvé un élément non nul
{ return false; }
else
{ return true; }
//ou : return i == v.size();
}

152. Algorithmique et programmation – L1 Stéphane Rivière


– Si tester un élément est compliqué :

– mettre le test dans une fonction booléenne et appeler cette fonction


dans la boucle
– utiliser la version avec le booléen present

153. Algorithmique et programmation – L1 Stéphane Rivière


18 Tableaux à deux dimensions
– On veut stocker et utiliser un ensemble de valeurs numérotées par deux
indices
– Par exemple les coefficients (aij ) d’une matrice A
– Un tableau à une dimension permet de stocker un ensemble de valeurs
numérotées par un indice
→ Rajouter un deuxième indice, et donc une deuxième dimension : tableau à
deux dimensions
– Techniquement, un tableau 2d est un tableau de tableaux 1d :

– t[i][j] est une case de tableau


→ t[i] est un tableau
→ t est un tableau de tableaux

154. Algorithmique et programmation – L1 Stéphane Rivière


18.1 Tableaux statiques à deux dimensions
– Déclarer un type tableau tableau en indiquant les tailles maximum TMAX1
et TMAX2 des deux dimensions

– en C++ :
using tableau = array<array<type_element,TMAX2>,TMAX1>;
!! la deuxième taille est donnée avant la première
– à l’ancienne :
using tableau = type_element[TMAX1][TMAX2];
– à l’ancienne façon C :
typedef type_element tableau[TMAX1][TMAX2];

– On déclare des variables, on passe des paramètres comme pour les ta-
bleaux à une dimension

155. Algorithmique et programmation – L1 Stéphane Rivière


– Pour accéder à une case du tableau : donner deux indices, correspondant
aux tailles indiquées
nom_variable[indice1][indice2]
– où 0≤indice1<TMAX1 et 0≤indice2<TMAX2
– C’est le problème qui décide à quoi correspond chaque dimension et le
sens de numérotation
– Par exemple : représentation d’une matrice A = (aij ) :

– i est le numéro de ligne, j de colonne


– le coefficient a00 est en haut à gauche
→ TMAX1 = nombre maximum de lignes et TMAX2 = nombre maximum
de colonnes

156. Algorithmique et programmation – L1 Stéphane Rivière


using coefficients = array<array<double,NBCOLONNESMAX>,NBLIGNESMAX>;
//ou using coefficients = double[NBLIGNESMAX][NBCOLONNESMAX];

void lireMatrice(coefficients& c, int& nbLignes, int& nbColonnes)


{
cout<<"nombre de lignes et de colonnes : ";
cin>>nbLignes>>nbColonnes;
for (int i=0; i<nbLignes; i++)
{
cout<<"coefficients ligne "<<i<<" : ";
for (int j=0; j<nbColonnes; j++)
{
cin>>c[i][j];
}
}
}

157. Algorithmique et programmation – L1 Stéphane Rivière


void afficherMatrice(const coefficients& c, int nbLignes, int nbColonnes)
{
for (int i=0; i<nbLignes; i++)
{
for (int j=0; j<nbColonnes; j++)
{
cout<<c[i][j]<<’ ’;
}
cout<<endl;
}
}

void testES()
{
coefficients c;
int nbLignes, nbColonnes;
lireMatrice(c, nbLignes, nbColonnes);
afficherMatrice(c, nbLignes, nbColonnes);
}

158. Algorithmique et programmation – L1 Stéphane Rivière


– Il vaut mieux regrouper le tableau et ses tailles dans une structure
using coefficients = array<array<double,NBCOLONNESMAX>,NBLIGNESMAX>;
struct matrice {
coefficients c;
int nbLignes, nbColonnes;
};

void lireMatrice(matrice& m)
{
cout<<"nombre de lignes et de colonnes : ";
cin>>m.nbLignes>>m.nbColonnes;
for (int i=0; i<m.nbLignes; i++)
{
cout<<"coefficients ligne "<<i<<" : ";
for (int j=0; j<m.nbColonnes; j++)
{
cin>>m.c[i][j];
}
}
}

159. Algorithmique et programmation – L1 Stéphane Rivière


void afficherMatrice(const matrice& m)
{
for (int i=0; i<m.nbLignes; i++)
{
for (int j=0; j<m.nbColonnes; j++)
{
cout<<m.c[i][j]<<’ ’;
}
cout<<endl;
}
}

void testES()
{
matrice m;
lireMatrice(m);
afficherMatrice(m);
}

160. Algorithmique et programmation – L1 Stéphane Rivière


– C’est à vous de choisir l’ordre de parcours des cases en fonction du pro-
blème :

– ordre des boucles


– sens de variation des boucles

– Si l’ordre des boucle n’est pas important :

– faire la première boucle sur le premier indice


– faire la boucle imbriquée sur le deuxième indice

161. Algorithmique et programmation – L1 Stéphane Rivière


– Produit matrice vecteur Y = AX :

– yi = produit de la ligne i de A par le vecteur X :


X
– yi = aij xj
j

void matriceFoisVecteur(const matrice& a, const vecteur& x,


vecteur& y)
{
y.taille = a.nbLignes;
for (int i=0; i<a.nbLignes; i++)
{
y.c[i] = 0;
for (int j=0; j<a.nbColonnes; j++)
{
y.c[i] = y.c[i] + a.c[i][j] * x.c[j];
}
}
}

162. Algorithmique et programmation – L1 Stéphane Rivière


– Produit vecteur matrice Y = XA :

– yj = produit de la colonne j de A par le vecteur X :


X
– yj = aij xi
i

void vecteurFoisMatrice(const vecteur& x, const matrice& a,


vecteur& y)
{
y.taille = a.nbColonnes;
for (int j=0; j<a.nbColonnes; j++)
{
y.c[j] = 0;
for (int i=0; i<a.nbLignes; i++)
{
y.c[j] = y.c[j] + a.c[i][j] * x.c[i];
}
}
}

163. Algorithmique et programmation – L1 Stéphane Rivière


– On peut décider aussi de ne parcourir qu’une partie du tableau :
P
– Trace d’une matrice carrée : tr(A) = i aii

double trace(const matrice& a)


{
double tr = 0;
for (int i=0; i<a.nbLignes; i++)
{
tr += a.c[i][i];
}
return tr;
}

164. Algorithmique et programmation – L1 Stéphane Rivière


18.2 Utilisation directe de tableaux C++
– On peut ponctuellement utiliser directement un tableau 2d sans déclarer
de type

18.2.1 Tableau C++ array


– variable : array<array<type,TMAX2>,TMAX1> t;
– paramètre en donnée : const array<array<type,TMAX2>,TMAX1>& t
– paramètre en résultat : array<array<type,TMAX2>,TMAX1>& t
void print(const array<array<int,20>,30>& t)
{
for (int i=0;i<30;i++) {
for (int j=0;i<20;i++) {
cout<<t[i][j]<<’ ’;
} array<array<int,20>,30> t;
} print(t);
}

165. Algorithmique et programmation – L1 Stéphane Rivière


18.2.2 Tableau à l’ancienne
– variable : typecases t[TMAX1][TMAX2];
– paramètre en donnée : const typecases t[TMAX1][TMAX2]
– paramètre en résultat : typecases t[TMAX1][TMAX2]
– Pour un paramètre : on peut ne pas indiquer TMAX2

void print(const int t[30][20])


{
for (int i=0;i<30;i++) {
for (int j=0;i<20;i++) {
cout<<t[i][j]<<’ ’;
}
}
}

int t[30][20];
print(t);

166. Algorithmique et programmation – L1 Stéphane Rivière


19 Tableaux à deux dimensions
– On veut stocker et utiliser un ensemble de valeurs numérotées par deux
indices
– Par exemple les coefficients (aij ) d’une matrice A
– Un tableau à une dimension permet de stocker un ensemble de valeurs
numérotées par un indice
→ Rajouter un deuxième indice, et donc une deuxième dimension : tableau à
deux dimensions
– Techniquement, un tableau 2d est un tableau de tableaux 1d :

– t[i][j] est une case de tableau


→ t[i] est un tableau
→ t est un tableau de tableaux

167. Algorithmique et programmation – L1 Stéphane Rivière


19.1 Tableaux dynamiques à deux dimensions
– Un tableau dynamique 2d est représenté par un tableau de tableaux 1d
– Déclarer un type tableau tableau

using tableau = vector<vector<type_element>>;

– Déclarer des variables de type tableau :

tableau t(taille1, vector<type_element>(taille2));

– Pour accéder à une case du tableau : donner deux indices, correspondant


aux tailles indiquées

t[indice1][indice2]

– où 0≤indice1<taille1 et 0≤indice2<taille2
– C’est le problème qui décide à quoi correspond chaque dimension et le
sens de numérotation

168. Algorithmique et programmation – L1 Stéphane Rivière


– On peut demander les tailles du tableau au tableau m :

– taille1 = m.size()
– taille2 = m[0].size()

– Exemple : eprésentation d’une matrice A = (aij ) :

– i est le numéro de ligne, j de colonne


– le coefficient a00 est en haut à gauche
→ taille1 = nombre de lignes et taille2 = nombre de colonnes

169. Algorithmique et programmation – L1 Stéphane Rivière


using matrice = vector<vector<double>>;

matrice matriceLue()
{
cout<<"nombre de lignes et de colonnes : ";
cin>>nbLignes>>nbColonnes;
matrice m(nbLignes, vector<double>(nbColonnes));
for (int i=0; i<nbLignes; i++)
{
cout<<"coefficients ligne "<<i<<" : ";
for (int j=0; j<nbColonnes; j++)
{
cin>>m[i][j];
}
}
matrice m;
}

170. Algorithmique et programmation – L1 Stéphane Rivière


void afficherMatrice(const matrice& m)
{
int nbLignes = m.size();
int nbColonnes = m[0].size();
for (int i=0; i<nbLignes; i++)
{
for (int j=0; j<nbColonnes; j++)
{
cout<<m[i][j]<<’ ’;
}
cout<<endl;
}
}

void testES()
{
matrice m = matriceLue();
afficherMatrice(m);
}

171. Algorithmique et programmation – L1 Stéphane Rivière


– C’est à vous de choisir l’ordre de parcours des cases en fonction du pro-
blème :

– ordre des boucles


– sens de variation des boucles

– Si l’ordre des boucle n’est pas important :

– faire la première boucle sur le premier indice


– faire la boucle imbriquée sur le deuxième indice

– Par exemple produits vecteur matrice :

using vecteur = vector<double>;


using matrice = vector<vector<double>>;

172. Algorithmique et programmation – L1 Stéphane Rivière


– Produit matrice vecteur Y = AX :
– yi = produit de la ligne i de A par le vecteur X
P
– yi = j aij xj
vecteur matriceFoisVecteur(const matrice& a, const vecteur& x)
{
int nbLignes = a.size();
int nbColonnes = a[0].size();
vecteur y(nbLignes);
for (int i=0; i<nbLignes; i++)
{
y[i] = 0;
for (int j=0; j<nbColonnes; j++)
{
y[i] += a[i][j] * x[j];
}
}
return y;
}

173. Algorithmique et programmation – L1 Stéphane Rivière


– Produit vecteur matrice Y = XA :
– yi = produit de la ligne i de A par le vecteur X
P
– yi = j aij xj
vecteur vecteurFoisMatrice(const vecteur& x, const matrice& a)
{
int nbLignes = a.size();
int nbColonnes = a[0].size();
vecteur y(nbColonnes);
for (int j=0; j<nbColonnes; j++)
{
y[j] = 0;
for (int i=0; i<nbLignes; i++)
{
y[j] += a[i][j] * x[i];
}
}
return y;
}

174. Algorithmique et programmation – L1 Stéphane Rivière


– On peut décider aussi de ne parcourir qu’une partie du tableau :
P
– Trace d’une matrice carrée : tr(A) = i aii

double trace(const matrice& a)


{
int nbLignes = a.size();
double tr = 0;
for (int i=0; i<nbLignes; i++)
{
tr += a[i][i];
}
return tr;
}

175. Algorithmique et programmation – L1 Stéphane Rivière


– Changer la taille d’un tableau dynamique 2d t est un peu plus compliqué
– Changer la taille1 :

t.resize(taille1);

– Changer la taille2 : il faut changer la taille de toutes les cases tableaux


de t

for (int i=0; i<t.size(); i++)


{
t[i].resize(taille2);
}

176. Algorithmique et programmation – L1 Stéphane Rivière


20 Les Fichiers texte
20.1 Introduction
– Les fichiers texte représentent des unités de stockage de texte (caractères)
sur un support physique

– ils ont un nom pour pouvoir les désigner et y accéder


– et un contenu, du texte, auquel on peut accéder

– Ils existent tant qu’on ne les efface pas

177. Algorithmique et programmation – L1 Stéphane Rivière


– Quand on écrit sur cout

– les données sont transformées en texte


– puis affichées sur l’écran

– Ce texte peut à la place être écrit dans un fichier :

– il suffit d’écrire dans une variable fichier en écriture à la place de cout

– Quand on lit depuis cin

– le texte tapé au clavier par l’utilisateur est lu et transformé en données

– Ce texte peut à la place être lu depuis un fichier :

– il suffit de lire depuis une variable fichier en lecture à la place de cin

178. Algorithmique et programmation – L1 Stéphane Rivière


20.2 écriture dans un fichier
– On a fait le programme suivant qui affiche une table de multiplication à
l’écran :

void afficherTableMult(int n)
{
cout<<table de multiplication de "<<n<<" : "<<endl;
for (int i=1; i<=12 ; i++)
{
cout<<i<<" * "<<n<<" = "<<i*n<<endl;
}
}

– On veut l’écrire dans un fichier pour pouvoir la lire plus tard, l’imprimer
...
– Pour utiliser les fichiers dans un programme : bibliothèque <fstream>

179. Algorithmique et programmation – L1 Stéphane Rivière


– Un fichier dans lequel on écrit est représenté par une variable fichier en
écriture de type ofstream
– Pour écrire dans un fichier il faut :

1. déclarer une variable fichier en écriture


ofstream f;
2. ouvrir le fichier en écriture en lui donnant son nom sur le disque
f.open(nom du fichier);
3. écrire dans la variable fichier (comme pour cout)
f<<...;
4. à la fin, fermer le fichier
f.close();

180. Algorithmique et programmation – L1 Stéphane Rivière


– On transforme la procédure pour qu’elle écrive la table dans un fichier de
nom stocké dans le paramètre nomfic

void ecrireTableMult(int n, const string& nomfic)


{
ofstream f; //déclaration variable fichier
f.open(nomfic); //ouverture du fichier
f<<table de multiplication de "<<n<<" : "<<endl;
for (int i=1; i<=12 ; i++) //écriture dans le fichier
{
f<<i<<" * "<<n<<" = "<<i*n<<endl;
}
f.close(); fermeture du fichier
}

181. Algorithmique et programmation – L1 Stéphane Rivière


void test()
{
string nomfic;
cout<<"nom du fichier ou écrire la table : ";
cin>>nomfic;
int n;
cout<<"numéro de la table : ";
cin>>n;
ecrireTableMult(n,nomfic);
}

– À la fin de l’exécution du programme, un fichier de nom le nom donné par


l’utilisateur est créé
– Si on l’ouvre, il contient la table de multiplication

182. Algorithmique et programmation – L1 Stéphane Rivière


– Quand on ouvre un fichier en écriture, il est d’abord vidé
– Si on veut écrire plusieurs choses ou plusieurs fois dans un fichier, on passe
plutôt la variable fichier en paramètre
– Un fichier est toujours passé en paramètre par référence (en résultat)

//ajoute la table de multiplication au fichier f


void ecrireTableMult(int n, ofstream& f)
{
f<<table de multiplication de "<<n<<" : "<<endl;
for (int i=1; i<=12 ; i++)
{
f<<i<<" * "<<n<<" = "<<i*n<<endl;
}
}

183. Algorithmique et programmation – L1 Stéphane Rivière


void test()
{
string nomfic;
cout<<"nom du fichier ou écrire la table : ";
cin>>nomfic;
ofstream f;
f.open(nomfic);
int n;
cout<<"numéro de la table (-1 pour finir) :";
cin>>n;
while (n!=-1)
{
ecrireTableMult(n,f);
cout<<"numéro de la table (-1 pour finir) :";
cin>>n;
}
f.close();
}

184. Algorithmique et programmation – L1 Stéphane Rivière


20.3 Lecture depuis un fichier
– On a fait le programme suivant qui demande des nombres et affiche leur
moyenne

void lireEtCalculerMoyenne(double& moyenne)


{
int n;
cout<<"nombre de valeurs : ";
cin>>n;
double somme = 0.0;
double val;
for (int i=0; i<n ; i++)
{
cout<<" valeur : ";
cin>>val;
somme = somme + val;
}
moyenne = somme / n;
}

185. Algorithmique et programmation – L1 Stéphane Rivière


– Plutôt que de retaper les valeurs à chaque fois on veut les écrire à l’avance
dans un fichier (avec un éditeur de texte) et lire les valeurs depuis ce fichier
– Un fichier depuis lequel on lit est représenté par une variable fichier en
lecture de type ifstream
– Pour lire depuis un fichier il faut :

1. déclarer une variable fichier en lecture


ifstream f;
2. ouvrir le fichier en lecture en lui donnant son nom sur le disque
f.open(nom du fichier);
3. lire depuis la variable fichier (comme pour cin)
f>>...;
4. à la fin, fermer le fichier
f.close();

186. Algorithmique et programmation – L1 Stéphane Rivière


– On transforme la procédure pour qu’elle lise les nombres depuis un fichier
de nom stocké dans le paramètre nomfic

void lireEtCalculerMoyenne(const string& nomfic, double& moyenne)


{
ifstream f; //déclaration variable fichier
f.open(nomfic); //ouverture du fichier
int n;
f>>n; //lecture depuis le fichier
double somme = 0.0; double val;
for (int i=0; i<n ; i++)
{
f>>val;
somme = somme + val;
}
f.close(); //fermeture du fichier
moyenne = somme / n;
}

– Remarque : pas besoin d’afficher les messages d’avertissement de saisie

187. Algorithmique et programmation – L1 Stéphane Rivière


– Quand on ouvre un fichier en lecture, la lecture commence au début du
fichier
– Si on veut lire plusieurs chose/fois depuis un fichier, il vaut mieux passer
la variable fichier en paramètre

//lit le fichier à partir de là où la lecture précédente s’est arrêtée


void lireEtCalculerMoyenne(ifstream& f, double& moyenne)
{
int n;
f>>n;
double somme = 0.0;
double val;
for (int i=0; i<n ; i++)
{
f>>val;
somme = somme + val;
}
moyenne = somme / n;
}

188. Algorithmique et programmation – L1 Stéphane Rivière


– Fichier qui contient plusieurs listes de valeurs :

void test()
{
string nomfic;
cout<<"nom du fichier où lire les valeurs : ";
cin>>nomfic;
ifstream f; //déclaration variable fichier
f.open(nomfic); //ouverture du fichier
int nbmoyennes;
f>>nbmoyennes;
double moyenne;
for (int i=1; i<=nbmoyennes; i++)
{
lireEtCalculerMoyenne(f,moyenne);
cout<<"moyenne "<<i<<" = "<<moyenne<<endl;
}
f.close(); fermeture du fichier
}

189. Algorithmique et programmation – L1 Stéphane Rivière


– Si le fichier contient la liste des valeurs sans indiquer en premier leur
nombre
– On peut tester si on a atteint la fin d’un fichier : f.eof() renvoie vrai si
on est à la fin du fichier, faux sinon
→ lire tant qu’on n’a pas atteint la fin du fichier
!! Attention : si après la dernière valeur il reste des espaces ou des sauts de
ligne dans le fichier, on n’est pas à la fin du fichier
→ utiliser alors ws :

– f>>ws fait avancer le curseur de lecture en sautant tous les espaces/saut


de ligne jusqu’à la prochaine valeur/fin du fichier

190. Algorithmique et programmation – L1 Stéphane Rivière


void lireEtCalculerMoyenne(ifstream& f, double& moyenne)
{
int n = 0; //nombre non connu à l’avance
double somme = 0.0;
double val;
while (!f.eof()) //tant qu’on n’est pas à la fin du fichier
{
f>>val>>ws;
n++;
somme = somme + val;
}
moyenne = somme / n;
}

– Attention : dans ce cas, on ne peut pas calculer plusieurs moyennes

191. Algorithmique et programmation – L1 Stéphane Rivière


20.4 Entrées/sorties
– Les fichiers sont un moyen de communication entre les programmes
– Un fichier créé par un programme peut être lu par un autre programme
– Un programme peut lire des données depuis un fichier créé par un autre
→ se mettre d’accord sur un format de fichier pour les données utilisées :
on doit pouvoir relier ce qu’on a écrit
– Si les données sont compliquées : découper dans différentes procédures

192. Algorithmique et programmation – L1 Stéphane Rivière


– Écriture/lecture d’un point : format (x, y)

struct point { double x,y; };

void ecrirePoint(const point& p, ofstream& f)


{
f<<’(’<<p.x<<’,’<<p.y<<’)’;
}

void lirePoint(point& p, ifstream& f)


{
char c;
f>>c>>p.x>>c>>p.y>>c;
}

193. Algorithmique et programmation – L1 Stéphane Rivière


– Fichier de points : nombre de points et points
– Créer un fichier de points tirés au hasard

void ecrirePointsHasard(int n,
double gauche, double droit,
double bas, double haut,
ofstream& f)
{
point p;
f<<n<<’ ’;
for (int i=1; i<=n; i++)
{
p.x = aleat(gauche, droit);
p.y = aleat(bas,haut);
ecrirePoint(p,f);
f<<’ ’;
}
f<<endl;
}

194. Algorithmique et programmation – L1 Stéphane Rivière


– Lire les points d’un fichier dans un tableau

using tabPoint = array<point,NPointsMax>; //ou = point[NPointsMax];


struct listePoints { tabPoint p; int n; };

void lirePoints(ifstream& f, listePoints& lp) {


f>>lp.n;
for (int i=0; i<lp.n; i++)
{ lirePoint(lp.p[i],f); }
}

using listePoints = vector<point>;

listePoints pointsLus(ifstream& f) {
int n; f>>n;
listePoints lp(n);
for (int i=0; i<n; i++)
{ lirePoint(lp[i],f); }
return lp;
}

195. Algorithmique et programmation – L1 Stéphane Rivière

Vous aimerez peut-être aussi