Вы находитесь на странице: 1из 102

COURS

D’INFORMATIQUE
Dominique Hermesse

Juin 2015
2

L’ordinateur
L’ordinateur est composé de quatre parties distinctes :
• Le processeur qui est composé
• d’une unité arithmétique et logique (UAL ou ALU en anglais) ou unité
de traitement qui effectue les opérations de base
• d’une unité de contrôle chargée du séquençage des opérations
• La mémoire qui contient à la fois les données et le programme
exécuté par l’unité de contrôle. Elle se divise entre :
• mémoire volatile ou RAM (Random Access Memory) qui contient
programmes et données en cours de traitement
• mémoire permanente ou ROM (Read Only Memory) qui stocke
programmes et données de base de la machine
• Les dispositifs d’entrée-sortie qui permettent de communiquer
avec le monde extérieur.
Les différents composants sont reliés par des bus
3

Les programmes
• Un programme est une suite d’instructions élémentaires, qui vont être
exécutées dans l’ordre par le processeur. Ces instructions
correspondent à des actions très simples, telles qu’additionner deux
nombres, lire ou écrire une case mémoire, etc.
• Chaque instruction est codée (physiquement cablée) en mémoire sur
quelques octets. Le processeur est capable d’exécuter des
programmes en langage machine, c’est-à-dire composés
d’instructions très élémentaires suivant un codage précis.
• Chaque type de processeurs est capable d’exécuter un certain
ensemble d’instructions, son jeu d’instructions.
• Pour écrire un programme en langage machine, il faut donc connaître
les détails du fonctionnement du processeur qui va être utilisé.
• Les langages de programmation utilisés de nos jours sont très
largement plus évolués que le langage machine. Néanmoins ils
reposent sur ce dernier : après compilation ils sont transformés
(traduits) en langage machine exécutable par le processeur.
4

Le processeur
• Le processeur, (ou CPU, Central Processing Unit, “ Unité
centrale de traitement ” en français) est le composant essentiel
d’un ordinateur qui interprète les instructions et traite les
données d’un programme.
• Le processeur est un circuit électronique complexe (circuit
intégré) qui exécute chaque instruction très rapidement, en
quelques cycles d’horloges.
• Toute l’activité de l’ordinateur est cadencée par une horloge
unique, de façon à ce que tous les circuits électroniques
travaillent tous ensemble de façon synchronisée.
• La fréquence de cette horloge s’exprime en MHz (millions de
cycles par seconde) ou GHz (milliards de cycles par
secondes).
• Par exemple, un processeur “Intel Core 2 Duo P8400 ”
possède une horloge cadencée à 2,26 GHz.
5

Principe de fonctionnement du
processeur
Pour chaque instruction, le processeur effectue
schématiquement les opérations suivantes :
• lire dans la mémoire principale l’instruction à exécuter
• effectuer le traitement correspondant à cette instruction
• passer à l’instruction suivante.
6

Caractéristiques d’un processeur


Un processeur est défini par :
•la largeur de ses registres internes de manipulation de
données (8, 16, 32, 64, 128 bits)
•la cadence de son horloge exprimée en MHz ou GHz
•le nombre de noyaux de calcul (core)
•son jeu d’instructions (ISA en anglais, Instructions Set
Architecture)
7

Structure d’un processeur


Le processeur est grossièrement divisé en deux parties :
• l’unité de contrôle
• L’unité de contrôle est responsable de la lecture en mémoire
principale et du décodage des instructions
• l’unité de traitement
• l’unité de traitement, aussi appelée Unité Arithmétique et Logique
(U.A.L.), exécute les instructions qui manipulent les données.
Ces deux unités communiquent avec la mémoire
principale, la première pour lire les instructions, la seconde
pour recevoir/transmettre des données binaires, mais ils
communiquent également avec les différents périphériques
(clavier, souris, écran,etc.).
8

Structure de la mémoire principale


La mémoire est divisée en emplacements (des cases
mémoires contiguës) de taille fixe (par exemple huit bits)
utilisés pour stocker instructions et données.
En principe, la taille d’un emplacement mémoire pourrait
être quelconque. En fait, la plupart des ordinateurs en
service aujourd’hui utilisent des emplacements mémoire
d’un octet (“ byte ” en anglais, soit huit bits, unité pratique
pour coder un caractère par exemple).
9

Adresse mémoire
Dans une mémoire de taille N, on a N emplacements
mémoires, numérotés (ou adressés) de 0 à N-1. Chaque
emplacement est repéré par un numéro unique, appelé
adresse. L’adresse est le plus souvent écrite en
hexadécimal.
10

Opérations sur la mémoire


Seul le processeur peut modifier l’état de la mémoire. Chaque
emplacement mémoire conserve les informations que le
processeur y écrit jusqu’à coupure de l’alimentation électrique,
où tout le contenu est perdu (contrairement au contenu des
mémoires externes comme les disquettes et disques durs). On
parle de mémoire vive.
Les seules opérations possibles sur la mémoire sont :
• Écriture d’un emplacement : le processeur donne une valeur et
une adresse, et la mémoire range la valeur à l’emplacement
indiqué par l’adresse ;
• Lecture d’un emplacement : le processeur demande à la
mémoire la valeur contenue à l’emplacement dont il indique
l’adresse. Le contenu de l’emplacement auquel le processeur
accède en lecture demeure inchangé
11

Caractéristiques de la mémoire
• La capacité : nombre total de bits que contient la mémoire. Elle
s’exprime aussi souvent en octets.
• Le format des données : nombre de bits que l’on peut mémoriser par
case mémoire. On parle de la largeur du mot mémorisable.
• Le temps d’accès : temps qui s’écoule entre l’instant où a été lancée
une opération de lecture/écriture en mémoire et l’instant où la
première information est disponible sur le bus de données.
• Le temps de cycle : il représente l’intervalle minimum qui doit séparer
deux demandes successives de lecture ou d’écriture.
• Le débit : nombre maximum d’informations lues ou écrites par
seconde.
• La volatilité : elle caractérise la permanence des informations dans la
mémoire. L’information stockée est volatile si elle risque d’être
altérée par un défaut d’alimentation électrique et non volatile dans le
cas contraire.
12

RAM
Nous savons qu’il existe deux types distincts de mémoire :
• Les mémoires mortes.
• Les mémoires vives.
• Une mémoire vive sert au stockage temporaire de données. Elle
doit avoir un temps de cycle très court pour ne pas ralentir le
microprocesseur.
• Les mémoires vives sont en général volatiles : elles perdent leurs
informations en cas de coupure d’alimentation. (Certaines d’entre
elles, ayant une faible consommation, peuvent être rendues non
volatiles par l’adjonction d’une batterie.)
• Il existe deux grandes familles de mémoires RAM (Random Acces
Memory : mémoire à accès aléatoire) :
• Les RAM statiques.
• Les RAM dynamiques.
13

RAM statique
Le bit mémoire d’une RAM statique (SRAM) est composé
d’une bascule (composant électronique élémentaire).
Chaque bascule contient entre quatre et six transistors.
14

RAM dynamique
Dans les RAM dynamiques (DRAM), l’information est mémorisée
sous la forme d’une charge électrique stockée dans un
condensateur.
Avantages :
• Cette technique permet une plus grande densité d’intégration,
car un point mémoire nécessite environ quatre fois moins de
transistors que dans une mémoire statique.
• Sa consommation s’en retrouve donc aussi très réduite
Inconvénient :
• La présence de courants de fuite dans le condensateur
contribue à sa décharge. Ainsi, l’information est perdue si on
ne la régénère pas périodiquement (charge du condensateur).
• Les RAM dynamiques doivent donc être rafraîchies
régulièrement pour entretenir la mémorisation : il s’agit de lire
l’information et de la recharger.
15

ROM
Pour certaines applications, il est nécessaire de pouvoir
conserver des informations de façon permanente même lorsque
l’alimentation électrique est interrompue. On utilise alors des
mémoires mortes ou mémoires à lecture seule (ROM : Read
Only Memory).
Ces mémoires sont non volatiles. Ces mémoires, contrairement
aux RAM, ne peuvent être que lues. L’inscription en mémoire
des données reste possible mais est appelée programmation.
Suivant le type de ROM, la méthode de programmation
changera. Il existe donc plusieurs types de ROM :
•ROM ;
•PROM ;
•EPROM ;
•EEPROM ;
•FLASH EPROM.
16

Composition d’un processeur


Les parties essentielles d’un processeur sont :
• L’ Unité Arithmétique et Logique (UAL, en anglais
Arithmetic and Logical Unit - ALU), qui prend en charge
les calculs arithmétiques élémentaires et les tests.
• L’unité de contrôle ou séquenceur, qui permet de
synchroniser les différents éléments du processeur. En
particulier, il initialise les registres lors du démarrage de la
machine et il gère les interruptions.
• Les registres, qui sont des mémoires de petite taille
(quelques octets), suffisamment rapides pour que l’UAL
puisse manipuler leur contenu à chaque cycle de
l’horloge. Un certain nombre de registres sont communs
à la plupart des processeurs.
17

Types de registres
• Compteur de programme :
• ce registre contient l’adresse mémoire de l’instruction en cours
d’exécution.
• Accumulateur :
• ce registre est utilisé pour stocker les données en cours de traitement
par l’UAL.
• Registre d’adresses :
• il contient toujours l’adresse de la prochaine information à lire par
l’UAL : soit la suite de l’instruction en cours, soit la prochaine
instruction.
• Registre d’instructions :
• il contient l’instruction en cours de traitement.
• Registre d’état :
• il sert à stocker le contexte du processeur, ce qui veut dire que les
différents bits de ce registre sont des “ drapeaux ” (flags) servant à
stocker des informations concernant le résultat de la dernière
instruction exécutée.
18

Types de registres
• Pointeurs de pile :
• ce type de registre, dont le nombre varie en fonction du type de
processeur, contient l’adresse du sommet de la pile (ou des piles).
• Registres généraux :
• ces registres sont disponibles pour les calculs.
• L’horloge :
• elle synchronise toutes les actions de l’unité centrale.
• L’unité d’entrée-sortie :
• elle prend en charge la communication avec la mémoire de
l’ordinateur, permettant au processeur d’accéder aux périphériques
de l’ordinateur.
19

Opérations du processeur
Le rôle fondamental de la plupart des unités centrales de
traitement, indépendamment de la forme physique qu’elles
prennent, est d’exécuter une série d’instructions stockées
appelées “ programme ”. Les instructions et les données
transmises au processeur sont exprimées en mots binaires
(code machine). Elles sont stockées dans la mémoire.
Le séquenceur ordonne la lecture du contenu de la mémoire et
la constitution des mots présentées à l’UAL qui les interprète.
L’ensemble des instructions et des données constitue un
programme. Le langage le plus proche du code machine tout en
restant lisible par des humains est le langage d’assemblage,
aussi appelé langage assembleur (forme francisée du mot
anglais “assembler ”).
Toutefois, l’informatique a développé toute une série de
langages, dits de haut niveau (comme le BASIC, Pascal, C,
C++), destinés à simplifier l’écriture des programmes.
20

Opérations du processeur
Le programme est représenté par une série d’instructions
qui réalisent des opérations en liaison avec la mémoire
vive de l’ordinateur. Il y a quatre étapes lors du traitement
des instructions :
•FETCH : Recherche de l’instruction
•DECODE : Décodage de l’instruction
•EXECUTE : Exécution des opérations
•WRITEBACK : Écriture du résultat
21

FETCH
La première étape, FETCH (recherche), consiste à
rechercher une instruction dans la mémoire vive de
l’ordinateur. L’emplacement dans la mémoire est
déterminé par le compteur de programme, qui stocke
l’adresse de la prochaine instruction dans la mémoire de
programme.
Après qu’une instruction a été recherchée, le compteur de
programme est incrémenté par la longueur du mot
d’instruction.
L’instruction que le processeur recherche en mémoire est
utilisée pour déterminer ce que le CPU doit faire.
22

DECODE
Dans l’étape DECODE (décodage), l’instruction est
découpée en plusieurs parties telles qu’elles puissent être
utilisées par d’autres parties du processeur.
La façon dont la valeur de l’instruction est interprétée est
définie par le jeu d’instructions du processeur.
Souvent, une partie d’une instruction, appelée opcode
(code d’opération), indique quelle opération est à faire, par
exemple une addition.
Les parties restantes de l’instruction comportent
habituellement les autres informations nécessaires à
l’exécution de l’instruction comme par exemple des valeurs
pour l’addition.
23

EXECUTE
Après les étapes de recherche et de décodage arrive l’étape
EXECUTE (exécution) de l’instruction.
Au cours de cette étape, différentes parties du processeur sont
mises en relation pour réaliser l’opération souhaitée.
Par exemple, pour une addition, l’unité arithmétique et logique
(UAL) sera connectée à des entrées et des sorties. Les entrées
présentent les nombres à additionner et les sorties contiennent
la somme finale.
L’UAL contient le circuit électronique pour réaliser des opérations
d’arithmétique et de logique simples sur les entrées (addition,
opération sur les bits). Si le résultat d’une addition est trop
grand pour être codé par le processeur, un signal de
débordement est positionné dans un registre d’état.
24

WRITEBACK
La dernière étape WRITEBACK (écriture du résultat), écrit
tout simplement les résultats de l’étape d’exécution en
mémoire.
Très souvent, les résultats sont écrits dans un registre
interne au processeur pour bénéficier de temps d’accès
très courts pour les instructions suivantes.
Dans d’autres cas, les résultats sont écrits plus lentement
dans des mémoires RAM, donc à moindre coût et
acceptant des codages de nombres plus grands.
25

Liaisons processeur-mémoire : les bus


Les informations échangées entre la mémoire et le
processeur circulent sur des bus. Un bus est simplement
un ensemble de n fils conducteurs, utilisés pour transporter
n signaux binaires.
Le bus d’adresse est un bus unidirectionnel : seul le
processeur envoie des adresses. Il est composé de n fils.
On utilise donc des adresses de n bits. La mémoire peut
posséder au maximum 2 n emplacements (adresses 0 à 2n
• -1).
Le bus de données est un bus bidirectionnel. Lors d’une
lecture, c’est la mémoire qui envoie un mot sur le bus (le
contenu de l’emplacement demandé). Lors d’une écriture,
c’est le processeur qui envoie la donnée.
26

La numération – le système décimal


Les nombres que nous utilisons habituellement sont ceux
de la base 10 (système décimal).
Nous disposons de dix chiffres différents de 0 à 9 pour
écrire tous les nombres.
Soit le nombre décimal 2348
Ce nombre est la somme de :
2 milliers, 3 centaines, 4 dizaines et 8 unités
(2 x 1000) + (3 x 100) + (4 x 10) + (8 x 1)
(2 x 10³) + (3 x 10²) + (4 x 101) + (8 x 100)
Quelle que soit la base, le chiffre de droite est celui des
unités.
Celui de gauche est celui qui a le poids le plus élevé.
27

La numération – le système binaire


En électronique les processeurs ne reconnaissent que deux
états :
•0 : absence de tension
•1 : présence de tension
Si on veut coder des nombres nous devons le faire en utilisant
ces deux chiffres 0 et 1
Analogie avec le décimal :
•10 chiffres base 10 => 2 chiffres base 2 (ou binaire)
•Base 10 combinaison des puissances de 10 => base 2
combinaison des puissances de 2
1101
(1 x 2³) + (1 x 2²) + (0 x 21) + (1 x 20)
(1 x 8) + (1 x 4) + (0 x 2) + (1 x 1)
=13 en décimal
28

La numération – l’hexadécimal
• L’écriture d’une valeur en binaire prend de la place
• 0101 1110 en binaire = 94 en décimal
• La conversion du binaire en décimal n’est pas facile
• L’hexadécimal est la solution car l’hexadécimal est une base
16 et 16 est une puissance de 2 => 24
Analogie avec le décimal :
• 10 chiffres base 10 => 16 chiffres base 16 (ou hexadécimal)
• 16 chiffres : 0 1 2 3 4 5 6 7 8 9 A B C D E F
• Avec : A=10, B=11, C=12, D=13, E=14 et F=15
• Base 10 combinaison des puissances de 10 => base 16
combinaison des puissances de 16
1A04
(1 x 16³) + (A x 16²) + (0 x 161) + (4 x 160)
(1 x 4096) + (10 x 256) + (0 x 16) + (4 x 1)
=6660 en décimal
29

La numération – l’hexadécimal
Conversion binaire en hexadécimal
•On groupe les bits par 4
•On convertit chaque groupe en hexadécimal

1001111100110101
1001 - 1111 - 0011 - 0101
8+1 - 8+4+2+1 - 2+1 - 4+1
9 - 15 - 3 - 5
9F35
30

La numération – l’hexadécimal
Conversion hexadécimal en binaire
•On convertit chaque chiffre en 4 chiffres binaires

43A1
4 - 3 - 10 - 1
4 - 2+1 - 8+2 - +1
0100 - 0011 - 1010 - 0001
0100001110100001
31

ASCII
Pour écrire des caractères, différents codes ont associés
des valeurs numériques à chaque caractère.
Le plus connu et utilisé est le code ASCII (American
Standard Code for Information Interchange), chaque
caractère est associé à une valeur comprise entre :
0 et 255
Ces valeurs peuvent toutes être codées sur 8 bits => 1
octet ou 1 byte => unité de calcul des tailles des mémoires
en informatique
32

ASCII
33

Algorithme et programmation
• Algorithme: méthode pour résoudre un problème
• Pour un problème donné, il peut y avoir plusieurs
algorithmes. . . ou aucun !

• On cherche des algorithmes simples, efficaces, élégants .


• Le programme: . . . s’adresse à une machine !
34

Le langage C++
• Début en 1983.
• Amélioration du langage C:
• Abstraction de données
• Programmation orientée objet
• Programmation générique
• Très utilisé !
35

Programmer
• Une fois trouvé l’algorithme, programmer en C++ comporte 4
phases :
1. Editer le programme – avec un éditeur de texte. Le fichier
programme appelé également fichier source portera l’extension
.cpp
2. Compiler et lier le programme. Le fichier .cpp va être compilé
et puis lié avec les éventuels fichiers d’entête que nous aurons
spécifiés et qui portent l’extension .h . Le fichier résultant est un
fichier exécutable avec l’extension .exe
3. Exécuter le programme
...
4. TESTER et DEBUGGER : retour au point 1 !
Ça peut durer assez longtemps...
36

Exemple

/* Ceci est notre premier programme


Il va afficher à l’écran hello world
*/
#include <iostream>
using namespace std ;

int main ( ) {
cout << ”hello world !” << endl; //Ecrit à l’écran “hello world”
}
37

Analyse de cet exemple


• Int main { }
• C’est la fonction principale
• C’est elle qui est exécutée en premier lieu
• On va y écrire le programme
• //Commentaire de ligne
• /*Commentaire
multi-lignes*/
• Include <iostream>
• Fichier d’entête
• Contient des déclarations de fonctions et variables que le
programme va utiliser
• iostream est le fichier d’entête pour les accès d’entrée/sortie à
l’écran
38

Analyse de cet exemple - suite


• using namespace std;
• Définit l’espace de nom dans lequel on va aller chercher les
variables cout et endl
• Ici c’est l’espace de nom standard de C++ appelé std
• Si on ne spécifie pas l’espace de nom avec using on doit accéder à
ces variables en utilisant l’opérateur de résolution de portée :: ce
qui donnerait std::cout ou std::endl
• cout<< permet d’afficher à l’écran une chaîne de
caractères
• endl permet de faire un saut de ligne
39

Lisibilité d’un programme


• Pour qu’un programme soit lisible
• Il ne faut pas hésiter à insérer des lignes vides pour séparer les
parties de programme
• Il faut bien commenter son programme
• Il faut jouer avec les tabulations pour bien faire apparaître les
entités entourées de { }
40

Programmation
Les briques de base du langage:

• Les variables qui permettent de stocker des données


• Les expressions qui permettent de manipuler les
données.
• Les instructions pour construire les algorithmes.
41

Les variables
• Les variables permettent donc de stocker durant
l’exécution du programme des données.
• Les variables ont un type et une valeur
• Les variables peuvent être globales ou locales
42

Types de variables élémentaires


• int : entiers (au min 16 bits, pour des valeurs comprises
entre – 32767 et + 32767) d’autres formats existent: long
(min 32 bits), short, unsigned int, . . .

• float, double et long double : nombres à virgule flottante


(en général 15 chiffres signés pour double). Par ex. 23.3
ou 2.456e12 ou 23.56e − 4

• char : caractères (’a’,’b’,. . . ’A’,. . . ,’:’,. . . )

• bool : booléens (’true’ ou ’false’).


43

Définition de variables élémentaires


Syntaxe : type v;
int Longueur ;
double Vitesse ;
•Toute variable doit être définie avant d’être utilisée !
•Une définition peut apparaître n’importe où dans un
programme.
•Une variable est définie jusqu’à la fin de la première
instruction composée (marquée par { }) qui contient sa
définition.
•Une variable définie en dehors de toute fonction est une
variable globale.
44

Initialisation des variables élémentaires


Une variable peut être initialisée lors de sa déclaration,
deux notations sont possibles :
• int longueur=34 ;
• double vitesse=12.34 ;
Ou bien
• int longueur (34) ;
• double vitesse (12.34) ;

Une variable d’un type élémentaire qui n’est pas initialisée,


n’a pas de valeur définie: elle peut contenir n’importe quoi.
45

Les constantes
Syntaxe : const type nom = val ;

• Par exemple: const float PI = 3.141592 ;

Il ne sera pas possible de modifier PI dans le reste du


programme (erreur à la compilation). . .
46

Types de variables complexes


Il existe également 2 types de variables complexes :

•Le tableau qui est un ensemble de variables du même


type

•La structure qui est un ensemble de variables de types


différents
47

Définition d’un tableau


Syntaxe : type nom [longueur];
int MonTableau [5];

•Toute variable doit être définie avant d’être utilisée !


•Une définition peut apparaître n’importe où dans un
programme.
•Une variable est définie jusqu’à la fin de la première
instruction composée (marquée par { }) qui contient sa
définition.
•Une variable définie en dehors de toute fonction est une
variable globale
48

Initialisation d’un tableau


Toutes les données d’un tableau sont indexées de 0 à
longueur-1
int MonTableau [5];
MonTableau [0]=3;

Dans notre exemple, les données du tableau MonTableau


sont indexées de MonTableau[0] à MonTableau[4]
49

Définition d’une structure


Syntaxe :
struct nom {
type nom var 1;
type nom var 2;

type nom var n;
};
•Toute variable doit être définie avant d’être utilisée !
•Une définition peut apparaître n’importe où dans un
programme.
•Une variable est définie jusqu’à la fin de la première instruction
composée (marquée par { }) qui contient sa définition.
•Une variable définie en dehors de toute fonction est une
variable globale
50

Initialisation d’une structure


Toutes les données d’une structure sont accessibles en
donnant le nom de la structure suivi du nom de la variable.
On placera un point entre les 2 noms.
struct MaStructure {
Int Longueur;
float Vitesse;
};
MaStructure.Longueur = 6;
MaStructure.Vitesse = 2.65;
51

Chaînes de caractères
Il existe une classe string, ce n’est un pas un type
élémentaire.
Pour l’utiliser, il faut placer en tête du fichier :
# include <string>;

• string toto ; définit toto comme une variable...


• string toto = "bonjour";
52

Expressions - affectation
En C/C++, l’affectation est une expression:

Soit v une variable (au sens large) et expr une expression.

v = expr affecte la valeur de expr à la variable v

Exemple :
Longueur = 12;
53

Opérateurs classiques
• Opérateurs arithmétiques:
*, +, -, / (division entière et réelle), % (modulo)

• Opérateurs de comparaison
< (inférieur), <= (inférieur ou égal), == (égal), > (supérieur),
>= (supérieur ou égal) et != (différent)

• Operateurs booléens
&& représente l’opérateur “ET”, || représente le “OU”, et !
représente le “NON”.
Par exemple, ((x<12) && ((y>0) || !(z>4)))
54

Entrées/sorties standards
• Le clavier et l’écran sont les entrées standards du système.
C’est grâce à elles que l’utilisateur va communiquer avec la
machine
• En programmation, on parlera de flux d’entrée ou de sortie
standard
• CIN pour le flux d’entrée clavier
• COUT pour le flux de sortie écran
• Ces deux flux sont définis dans le fichier d’entête
<IOSTREAM>
• Vu qu’ils font partie de la bibliothèque standard on les
programmera en les précédent de STD::
• STD::CIN ou STD::COUT
• On peut également déclarer l’espace de nom standard en
début de programme
• USING NAMESPACE STD;
• On utilisera alors CIN OU COUT sans ajouter ::STD
55

Entrées/sorties standards
• Les flux CIN et COUT seront suivis des opérateurs
d’insertion << pour COUT et >> pour CIN
• L’opérateur d’insertion << permet donc d’écrire sur le flux
COUT (écran)
• L’opérateur d’insertion >> permet de lire sur le flux CIN
(clavier)
56

Syntaxe flux COUT


cout < < expr1 < < . . . < < exprn
• expr1..exprn seront soit des chaines de caractères
entourées de " " ou bien des variables
Int age = 15;
cout<< "j’ai "<<age<< " ans"<<endl;
• Pour introduire un saut de ligne, on peut utiliser le
manipulateur ENDL
• Dans les chaînes de caractères on peut utiliser des
caractères spéciaux (tabulation, saut de ligne, …). Ils
seront représentés par des lettres précédées de \
• \n saut de ligne
• \t tabulation
57

Syntaxe flux CIN


cin > > var1 > > . . . > > varn
• var1 .. Varn seront les variables dans lesquelles les
données lues au clavier seront mémorisées
• Le type des variables définira le codage de la donnée lors
de sa mémorisation
• Si les données présentes dans le flux sont incompatibles
avec le type de la variable de destination le flux CIN se
bloquera et il ne pourra plus être utilisé
58

Déblocage flux CIN


• Pour savoir si le flux CIN est bloqué, il suffit de
l’interroger. Il renverra un TRUE s’il est OK et un FALSE
s’il est bloqué.
• Pour le débloquer on travaillera en deux étapes :
• cin.clear(); // pour effacer les bits d'erreurs
• cin.ignore( numeric_limits<streamsize>::max(), '\n' ); // pour
supprimer la ligne erronée dans le buffer
On demande d'ignorer le maximum de caractères différents de '\n'
Ce maximum est obtenu grâce à numeric_limits repris dans le fichier
d’entête Limits
numeric_limits<streamsize>::max() correspond à la taille maximum
du buffer d'entrée clavier en octets
cin.ignore(x,'\n') ignore x caractère dans le buffer clavier, mais s'il
rencontre \n il s'arrête
59

Déblocage flux CIN


#include <iostream>
#include <windows.h> //entête pour l’accès aux fonctions de Windows
#include <limits> //entête pour l’utilisation de numeric_limits

using namespace std;

int main ()
{
float valeur=0;

cout << "Entrez un nombre : ";

while ( ! ( cin >> valeur ) ) // tant que la valeur n’est pas un nombre CIN bloqué => on boucle
{
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );

system ("cls");//Efface l'écran avec l'include Windows.h

cout << "Entrez un nombre : ";


}
cout << "Le nombre entré est " << valeur << ".\n";

}
60

Instructions usuelles
• Instructions de test :
• if … then
• if … then … else
• Instructions de boucle :
• while …
• do … while
• for …
• Instruction d’évaluation de cas :
• switch … case … case
61

Instructions de test
if (condition) instr
if (v == 3) i =i+4 ;
ATTENTION == est différent de =
if (condition) instr1 else instr2
if ((v==3) && (i<5))
{
i=i+4 ;
v=v*2 ;
}
else
{
v=i ;
r = r*3 ;
}
62

Instruction de boucle - while


while (condition)
{
instr

}

int Condition = 0;
int I = 0;
while (Condition<5)
{
I=I+2;
Condition++ //Incrémente Condition d’une unité
}
63

Instruction de boucle - for


for (indexe ; condition ; incr index)
{
instr

}

int MonTableau [5];


for (int Index=0 ; Index<5 ; ++Index)
{
MonTableau[Index] = 0;
}

Idéalement l’index est déclaré dans la boucle et donc n’aura une


portée que sur la boucle (variable locale).
64

Instruction évaluation cas - switch


switch (critère)
{
case 0:
{
instr;
…;
break; //Permet de ne pas exécuter les autres cas
}
case 1:
{
instr;
…;
break; //Permet de ne pas exécuter les autres cas
}
case x:
{
instr;
…;
break; //Permet de ne pas exécuter les autres cas
}
Default: //Traité si autre valeur que 0,1,…,x
{
instr;
…;
}
}
65

Fonctions et procédures
• Les fonctions et procédures sont des morceaux de
programme qui :
• Servent à structurer le programme
• Peuvent être réutilisées plusieurs fois
• Peuvent être mises dans des bibliothèques pour être utilisées dans
d’autres programmes
• Fonctions et procédures peuvent être paramétrées
• Les fonctions renvoient un et un seul résultat
• Les procédures ne renvoient pas de résultat
66

Fonctions et procédures
• Les fonctions et procédures doivent être définies :
• La définition est la programmation de la fonction ou de la procédure
• La définition peut être faite à différents endroits :
• Dans la fonction main () , mais c’est très rare
• Avant la fonction main ()
• Dans un autre fichier

• Les fonctions et procédures doivent être déclarées :


• Comme les différentes variables
• Avant d’être utilisées
• De manière globale ou locale
67

Fonctions et procédures - syntaxe


type nom( liste des paramètres) { corps }
•Le type est le type du résultat pour la fonction, ce sera
void pour les procédures.
•La liste des paramètres permet de passer des données à
la fonction ou la procédure
• type1 param1, ..., typen paramn
•Le corps décrit les instructions à effectuer. Le corps utilise
ses propres variables locales, les éventuelles variables
globales et les paramètres.
•Pour la fonction, l’instruction return valeur permet de
retourner le résultat.
•Dans le cas d’une procédure, on peut utiliser: return;
68

Exemple de fonction
#include <iostream>

using namespace std;

int somme(int,int); //Déclaration de la fonction « somme »


//ou int somme(int a,int b);

int somme(int a,int b) //Définition de la fonction « somme »


{
int retour=0;

retour = a+b;
return retour;
}

int main ()
{
int x=2;
int y=3;

cout<<somme(x,y);
}
69

Exemple de procédure
#include <iostream>

using namespace std;

void AuRevoir () // Définition de la procédure « AuRevoir »


{
cout<<"Au Revoir !";
return;
}
int main ()
{
void AuRevoir (); // Déclaration de la procédure « AuRevoir »;

AuRevoir();
}
70

Les références
• Lors de la définition d’une variable, on peut créer une ou
plusieurs variables qui y font référence
• Ce sont des « Alias » de la variable
• Les variables références portent un nom
• Le type de la référence est le même que celui de la variable suivi
de &
• Elles sont intimement liées à la variable
• Lorsqu’on affecte une référence, la variable est modifiée
• On initialise toujours la référence en y affectant la variable
71

Les références
• Syntaxe :

type variable;
type& nom_référence = variable;

• Exemple :

float Temperature = 0;
float& ReferenceTemperature = Temperature;

ReferenceTemperature = 145,023
//La variable Temperature vaut maintenant 145,023
72

Les pointeurs
• On peut également accéder à une variable en utilisant
son adresse dans la mémoire
• La variable qui va contenir cette adresse s’appelle un
pointeur
73

Les pointeurs
• Syntaxe :
• type* nom;
• nom est un pointeur pouvant recevoir l’adresse d’une variable de type
type.
• &Vitesse représente l’adresse mémoire de la variable Vitesse
• *PointeurVitesse désigne la variable dont l’adresse est mémorisée
dans le pointeur PointeurVitesse
• Exemple :
float Vitesse = 45.56;
float* PointeurVitesse;

PointeurVitesse = &Vitesse;
//Le pointeur reçoit l’adresse de vitesse
*PointeurVitesse = 89.56;
//La variable pointée par le pointeur (ici Vitesse) reçoit 89,56
74

Les pointeurs

Adr hex Mémoire Variable

0154
0158 45.56 Vitesse
015C
015F

021C
021F
0220
0224 Hex 0158 PointeurVitesse
75

Cas particulier – les tableaux


• Rappel de la déclaration d’un tableau
Syntaxe : type nom [longueur];
int MonTableau [5];
• MonTableau est un pointeur qui pointe sur la première
case du tableau
• Passer un tableau en paramètre d’une fonction revient à
passer l’adresse de la première case, c’est donc un
passage par pointeur.
• Pour déclarer comme paramètre MonTableau de type
tableau d’entiers, on écrit: int MonTableau[].
• La taille doit être passée avec un autre paramètre.
76

Cas particulier – les tableaux


int add(int tableau[],int taille)
{
int retour=0;
for(int i=0;i<taille;++i)
{
retour=retour+tableau[i];
}
return retour;
}

int main ()
{
int add(int* ,int );
int tab[3]={1,2,3};
int somme=0;
somme=add(tab,3);
}
77

Chaînes de caractères
• Une chaîne de caractères est une suite de variables de type
« CHAR »
• Pour mémoriser une chaîne de caractères on créera donc un
tableau de CHAR
char MaChaine [10];
• On peut affecter directement un flux d’entrée au tableau
cin>>MaChaine;
• Lors de la fin saisie avec la touche « enter » le code ASCII 0 est
introduit dans le tableau
• 0 ne correspond à aucun caractère et sera interprété comme la fin de
la chaîne de caractères
• On peut directement envoyer le tableau vers le flux de sortie
cout<<MaChaine
• Tous les caractères mémorisés dans la chaîne seront affichés jusqu’au
caractère de fin de chaîne 0
78

Chaînes de caractères
• Pour initialiser le tableau de caractères on peut :
• Faire une boucle et initialiser caractère par caractère
• Ecrire char Chaine[10]={'B','o','j','o','u','r'};
• Ecrire char Chaine[10]="Bonjour";
• Pour le traitement du tableau de caractères, il faut
l’analyser élément par élément
• On ne peut pas comparer directement deux chaînes de caractères,
il faut le faire caractère par caractère
• On ne connaît pas la longueur de la chaîne de caractère, il faut
initialiser la chaîne avec, par exemple, la valeur numérique 0 qui ne
correspond à aucun caractère ASCII et puis, analyser caractère par
caractère et rechercher le caractère ‘\0’
79

Les données structurées


• Une structure c’est comme un tableau, c’est un ensemble
de données
• Une structure est un ensemble de données de types
différents, alors que pour le tableau toutes les données
sont du même type
• Une structure se déclare hors du main et puis, est utilisée
comme un type de donnée simple
• L’accès à un élément de la structure se fait en écrivant le
nom de la variable suivi d’un point et puis du nom de la
donnée de la structure à laquelle on veut accéder
80

Les données structurées


• Déclaration de la structure :

struct voiture
{
char Marque [10];
char Modele [10];
int Puissance;
};

• Utilisation du type structuré :

Int main ()
{
voiture MonAuto;

cin>>MonAuto.Marque;
cin>>MonAuto.Modele;
cin>>MonAuto.Puissance;
}
81

Lire et écrire dans un fichier


• La première chose à faire quand on veut manipuler des
fichiers, c'est de les ouvrir
• Une fois le fichier ouvert, tout se passe comme pour cout
et cin
• On parle également de flux, mais plus de flux
d’entrée/sortie, mais flux vers les fichiers
• Pour les flux d’entrée/sortie cout et cin, nous avions
besoins du fichier d’entête IOSTREAM
• Pour les flux vers les fichiers, nous aurons besoin du
fichier d’entête FSTREAM (F de file et STREAM pour flux)
82

Ouvrir un fichier en écriture


• Une différence avec les flux d’entrée/sortie est que pour
les fichiers, il faut créer un flux par fichier.
• Nous sommes en programmation objet et le flux est un
objet. Nous retrouverons une série de fonctions pour
manipuler le flux
• Ouverture
• Fermeture
• Retour au début
• Le flux devra être déclaré comme une variable avant
d’être utilisé
• Dans notre cas le type sera OFSTREAM et la valeur sera
le chemin d’accès au fichier à lire
83

Ouvrir un fichier en écriture


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

int main()
{
ofstream monFlux("monfichier.txt");
/*Déclaration d'un flux permettant d'écrire dans le fichier
monfichier.txt */
}
84

Chemin d’accès au fichier


• Le chemin d’accès au fichier peut avoir deux formes :
• Un chemin absolu, c'est-à-dire montrant l'emplacement du fichier
depuis la racine du disque. Par exemple : C:\C++\Fichiers/scores.txt.
• Un chemin relatif, c'est-à-dire montrant l'emplacement du fichier
depuis l'endroit où se situe le programme sur le disque. Par exemple :
Fichiers\scores.txt si mon programme se situe dans le dossier
C:\C++\.
• À partir de là, on peut utiliser le flux pour écrire dans le fichier.
• Si le fichier n'existait pas, le programme le créerait
automatiquement ! Par contre, il faut que le dossier existe.
Dans l'exemple précédent, le dossier C:\C++\Fichiers doit
exister. Si ce n'est pas le cas, rien ne sera écrit.
85

Syntaxe chemin d’accès au fichier


• Le nom du fichier et son chemin d’accès vont donc être
encodés comme une chaîne de caractères entourée de " "
• Or dans les chaînes de caractères, on peut définir des
caractères spéciaux en utilisant le \ suivi d’une lettre
• "\n" qui correspond à un saut de ligne comme endl
• "\t" qui correspond à une tabulation
• Les \ que nous allons donc utiliser dans le chemin d’accès
au fichier vont être interprétés par le compilateur comme
des caractères spéciaux. Pour éviter cela, il y a 2
possibilités :
• Doubler le \ => "c:\\datas\\fichier.txt"
• Remplacer le \ par le / => "c:/datas/fichier.txt"
86

Nom fichier mémorisé


• Le nom et le chemin d’accès au fichier peuvent être
mémorisés dans une variable de type chaîne de
caractères
char NomFichier[20];

cout<<"Nom du fichier : ";


cin>>NomFichier;

ofstream monFlux(NomFichier);
87

Fermeture du fichier
• Le flux de lecture ou d’écriture du fichier est fermé
lorsqu’on sort de la partie de programme dans laquelle le
flux à été créé => lorsqu’on arrive à }
• Si on veut fermer prématurément le flux, on utilisera la
fonction close du flux
monFlux.close();
• Si on lit dans un fichier et puis qu’on écrit dans le même
fichier, il faudra s’assurer que la lecture et l’écriture sont
programmées dans 2 parties de programme différentes
ou bien il faudra fermer le premier flux avant d’ouvrir le
suivant. C’est valable également dans le cas inverse où
on écrit dans un fichier et puis qu’on lit dans le même
fichier
88

Gestion erreurs d’ouverture fichier


• Des problèmes peuvent survenir lors de l'ouverture d'un
fichier, si le fichier ne vous appartient pas ou si le disque
dur est plein par exemple
• Il faut TOUJOURS tester si tout s'est bien passé. On
utilise pour cela la syntaxe if(monFlux). Si ce test n'est
pas vrai, alors c'est qu'il y a eu un problème et que l'on ne
peut pas utiliser le fichier.
89

Gestion erreurs d’ouverture fichier


ofstream monFlux("C:\\monfichier.txt");
//On essaye d'ouvrir le fichier

if(monFlux) //On teste si tout est OK


{
//Tout est OK, on peut utiliser le fichier
}
else
{
cout << "ERREUR: Impossible d'ouvrir le fichier." << endl;
}
90

Ecrire dans un fichier


• Comme pour le flux de sortie cout, nous utiliserons <<

char nom[10];
int age=0;
cout<<"Quel est ton nom : ";
cin>>nom;
cout<<"Quel est ton age : ";
cin>>age;
monFlux << "Bonjour, je m’appelle " << nom << endl;
monFlux << "J'ai " << age << " ans." << endl;
91

Différents modes d’ouverture


• Si le fichier existe déjà lors de sa création, il sera
supprimé et remplacé par ce que vous écrivez.
• Pour pouvoir écrire à la fin d'un fichier, il faut le spécifier
lors de l'ouverture en ajoutant un deuxième paramètre à
la création du flux :
ofstream monFlux("C:\\scores.txt", ios::app);.
• app est un raccourci pour append, le verbe anglais qui
signifie « ajouter à la fin ».
92

Ouvrir un fichier en lecture


• Comme pour l’écriture il faut déclarer un nouveau flux comme
on le fait pour une variable
• Le type sera IFSTREAM et la valeur, le nom et le chemin
d’accès au fichier
ifstream monFlux("C:\\monfichier.txt");
• Il faudra également tester le flux pour vérifier que le fichier est
bien ouvert
If(monFlux)
{
//Gestion du flux
}
else
{
cout<< " Le fichier ne s’est pas ouvert " <<endl;
}
93

Lire les données du fichier


Il y a trois méthodes pour lire les données du fichier :
• Ligne par ligne, en utilisant getline()
• Caractère par caractère, en utilisant get()
• Mot par mot, en utilisant les chevrons >> ;
94

Lecture ligne par ligne


• La première méthode permet de récupérer une ligne
entière et de la stocker dans une chaîne de caractères de
type string et non pas dans un tableau de char
string ligne ;
getline(monFlux, ligne); //On lit une ligne complète
• En testant getline avec un if, on sait s’il reste une ligne
après. En effet, getline renvoie un 1 logique s’il reste au
moins une ligne après celle en cours et un 0 logique si on
est sur la dernière ligne du fichier
95

Lecture caractère par caractère


Pour lire caractère par caractère, on utilise la méthode get
de notre flux
char a;
monFlux.get(a);
• Ce code lit une seule lettre et la stocke dans la variable a.
• Cette méthode lit réellement tous les caractères. Les
espaces, retours à la ligne et tabulations sont, entre
autres, lus par cette fonction.
• Comme pour getline, l’état logique de monFlux.get() est 1
s’il reste un caractère après et 0 si nous sommes sur le
dernier caractère du fichier.
96

Lecture mot par mot


• On peut lire mot par mot, mais en créant des variables
avec le type des mots à lire
float nombre;
monFlux >> nombre; //Lit un nombre réel depuis le fichier
char mot[10];
monFlux >> mot; //Lit un mot depuis le fichier et clôture la
chaîne de caractère par un 0
• Cette méthode lit ce qui se trouve entre l'endroit où l'on se
situe dans le fichier et l'espace ou le saut de ligne suivant.
Ce qui est lu est alors traduit en double, int ou char selon
le type de variable dans lequel on écrit.
97

Détecter la fin de fichier


• Nous avons vu qu’avec la lecture ligne par ligne GETLINE
et caractère par caractère monFlux.GET(), le fait
d’interroger le retour binaire de ces fonctions permet de
savoir s’il reste une ligne ou un caractère à la suite du
curseur.
• On peut également utiliser la fonction EOF (end of file) du
flux qui renvoie un 1 logique lorsqu’on est arrivé à la fin
du fichier
while (!monFlux.EOF())
{

}
98

Se situer dans un fichier


• Lorsqu’on lit ou écrit dans un fichier, on s’y déplace
comme lorsqu’on le fait avec un éditeur classique
• Si j’écris dans un fichier, le curseur vient se placer à la
suite de ce qui vient d’être écrit
• Si je lis une ligne, un mot ou un caractère, le curseur se
place à la suite de ce qui vient d’être lu
• On a la possibilité de connaître la position du curseur et
éventuellement de le déplacer dans le fichier
99

Lire la position du curseur


• Pour connaître la position du curseur, nous allons utiliser une
fonction sur les flux
• La fonction n’est pas la même pour les flux entrant ou sortant
• La fonction renvoie la position en octets => en caractères dans
le fichier
• Pour le flux entrant IFSTREAM qui permet de lire dans un
fichier, la fonction est TELLG() (G de get obtenir)
• Pour le flux sortant OFSTREAM qui permet d’écrire dans le
fichier, la fonction est TELLP() (P de put placer)
• On écrira :
ifstream monFlux("C:\\monfichier.txt");
int Position=0;
position = monFlux.tellg();
100

Déplacer le curseur
• Nous utiliserons également une fonction sur les flux pour
déplacer le curseur
• Il y a également 2 fonctions
• Pour le flux entrant IFSTREAM ce sera SEEKG()
• Pour le flux sortant OFSTREAM ce sera SEEKP()
• Le déplacement se fait toujours par rapport à une position
que l’on entrera dans la fonction comme paramètre
• Il y a 3 positions :
• le début du fichier : ios::beg
• la fin du fichier : ios::end
• la position actuelle : ios::cur
• Attention : le retour de ligne ‘\n’ occupe 2 emplacements
101

Déplacer le curseur
• On écrira pour se déplacer de 15 caractères à partir du
début du fichier :
ifstream monFlux("C:\\monfichier.txt");
int Position=15;
monFlux.seekg(Position,ios::beg);
• On écrira pour se déplacer de 5 caractères à partir de la
position du curseur :
ifstream monFlux("C:\\monfichier.txt");
monFlux.seekg(5,ios::cur);
• La position est un entier qui peut être positif ou négatif
102

Taille du fichier
• Pour connaître la taille d’un fichier
• On se place à la fin du fichier
• On demande la position du curseur

Вам также может понравиться