poly copies mas 3
TRANSCRIPT
PROGRAMMATION ALGORITHMIQUE LANGAGE C/C++. | Prof. E. El Bachari
VERSION 1.0 ALGORITHMIQUE & PROGRAMMATION
LANGAGE C/C++.
Page 2
Introduction
Apparu au début des années 90, le langage C++ est actuellement l’un des plus utilisés dans le monde, aussi
bien pour les applications scientifiques que pour le développement des logiciels. En tant qu’héritier du
langage C, le C++ est d’une grande efficacité. Mais il a en plus des fonctionnalités puissantes, comme par
exemple la notion de classe, qui permet d’appliquer les techniques de la programmation-objet.
Le but de ce cours est de présenter la syntaxe de base du langage C++. La programmation-objet, quant à elle,
sera abordé dans un autre cours au deuxième semestre.
Ce document est la compilation de notes de cours Algorithmique et programmation C/C++ données aux
étudiants de la filière Mathématiques (SMA S3) à la faculté des sciences Semlalia Université Cadi A à
Marrakech.
Toute remarque ou erreur peut être notifiée à l’auteur à l’adresse électronique suivante : [email protected]
Plan du cours o Chapitre I. Généralités
o Chapitre II. Identificateurs, types et variables
o Chapitre III. Opérateurs, expressions et conversions
o Chapitre IV. Entrées/Sorties
o Chapitre V. Instructions de contrôle
o Chapitre VI. Fonctions
o Chapitre VII. Tableaux et pointeurs
Page 3
Chapitre I. Généralités
Introduction
Programmer un ordinateur, c’est lui fournir une série d’instructions qu’il doit exécuter. Ces instructions sont
généralement écrites dans un langage dit évolué, puis, avant d’être exécutées, sont traduites en langage
machine (qui est le langage du microprocesseur). Cette traduction s’appelle compilation et elle est effectuée
automatiquement par un programme appelé compilateur.
Pour le programmeur, cette traduction automatique implique certaines contraintes :
– il doit écrire les instructions selon une syntaxe rigoureuse,
– il doit déclarer les données et fonctions qu’il va utiliser (ainsi le compilateur pourra réserver aux données
une zone adéquate en mémoire et pourra vérifier que les fonctions sont correctement employées).
La seule langue connue par l’ordinateur est le langage binaire (machine) qui ne s’écrit qu’avec les chiffres 0
et 1. Dans notre cas, on va étudier le langage de programmation C++. C’est un langage à vocation générale, il
est efficace dans les applications commerciales, la programmation système et dans les applications
techniques.
La présentation du système en couches
Usager
Langage
Compilateur
Système
Hardware
Page 4
La structure d’un programme C++
Un programme C++, se compose de trois parties
1
2
3
1- Les fichiers en-tête
Ils sont composés des instructions < include >. Ils contiennent les données, des types et des fonctions
utilisées par le compilateur.
2- Les déclarations
Cette partie contient les déclarations et les définitions de toutes les variables et fonctions.
3- Le corps du programme
Cette partie contient des fonctions utilisées dans le programme. Un programme C++ peut contenir un
nombre indéfini de fonctions. Il doit au minimum en contenir une appelée main.
Cette fonction obligatoire constitue la fonction principale de tout le programme C++. Elle contient les
instructions exécutées au démarrage du programme. Elle a la forme suivante:
Les fichiers en-tête
Les déclarations
Le corps du programme
Page 5
• Directives au processeur - C’est une ligne de programme commençant par le caractère #.
- Elle permet de manipuler le code du programme source avant sa compilation.
- Parmi les directives, on trouve : inclusions de fichiers, substitutions, macros, compilation conditionnelle.
- La ligne « #include <iostream>» est interprétée par le préprocesseur qui recherche dans des répertoires
standards le fichier dont le nom est « iostream ».
- Si le préprocesseur trouve ce fichier, il l’« inclut » en lui faisant subir le même traitement que le fichier
initial (traitement des lignes commençant par #, recherche des macros etc.).
- Ce simple programme nécessite l’inclusion du fichier externe « iostream » contenant les méthodes
nécessaires pour manipuler les entrées et les sorties.
• Espace de noms
- La bibliothèque standard C++ est définie dans son propre espace de noms, un bloc (ou espace) portant le
nom « std ».
- La directive « using namespace std » dit au compilateur que toutes les choses définies dans « std » doivent
être rendues accessibles pour être directement utilisées.
- La bibliothèque « std » contient par exemple la définition de la fonction « cout » utilisée pour l’affichage en
sortie.
Programme Principal - La fonction « main » est le point d’entrée d’un programme C++.
- C’est à travers cette fonction « main » qu’un programme C++ démarre.
- La signature de la méthode « main » peut-être avec paramètres ou sans, comme suit:
Page 6
-Les paramètres « argc » et « argv » permettent de récupérer les arguments de la ligne de commande qui a
lancé ce programme.
- La variable « argc » représente le nombre d'arguments, nom du programme compris.
- La variable « argv » est un tableau de chaînes de caractères contenant la liste des arguments.
- La méthode « main » retourne une valeur entière représentant l’état de l’exécution du programme.
- La valeur entière retournée est par convention positive non nulle en cas d’erreur.
- Dans notre exemple, la valeur retournée est « 0 » pour signifier que l’exécution du programme s’est faite
correctement.
Génération d’un programme exécutable
Le développement d’un programme passe par trois phases successives :
1) écriture et enregistrement des différents fichiers-source,
2) compilation séparée des fichiers .cpp, chacun d’eux donnant un fichier-objet portant le même nom, mais
avec l’extension .obj,
3) lien des fichiers-objets (assurée par un programme appel´e linker) pour produire un unique
fichier-exécutable, portant l’extension .exe ; ce dernier pourra être lancé et exécuté directement depuis le
système d’exploitation.
Les différentes étapes intervenant dans le processus d’élaboration d’un programme exécutable sont comme
suit :
Page 7
Les outils nécessaires au programmeur Voici le strict minimum pour un programmeur :
• Un éditeur de texte pour écrire le code source du programme en C++. En théorie un logiciel comme le
Bloc-Notes sous Windows ou vi sous Linux fait l'affaire. L'idéal, c'est d'avoir un éditeur de texte
intelligent qui colore tout seul le code, ce qui permet de s’y repérer bien plus facilement.
• Un compilateur pour transformer (« compiler ») le code source en binaire.
• Un débugger (« Débogueur » ou « Débugueur » en français) pour traquer les erreurs dans le programme
N.B. On n'a malheureusement pas encore inventé le « correcteur », un truc qui corrigerait tout seul nos
erreurs).
Il existe plusieurs environnements de développement IDE incluant ces trois outils.
• Visual Studio .NET
Page 8
• Visual C++ 2005 Express
• Borland C++ Builder
• Code::Blocks
• Dev C++
• Eclipse + CDT
• etc.
Pour ce cours, nous allons utiliser le compilateur gratuit du domaine public le plus récent g++. Comme IDE
nous optons pour Code::Blocks incluant entre autre ce compilateur. Il est également gratuit et disponible
pour la plupart des systèmes d'exploitation (Linux, Macintosh, Windows). La figure suivante inclut toutes
les commandes nécessaires (variantes) pour compiler un code.
Page 9
Chapitres II. Identificateurs, types et variables
Les éléments du langage
Pour écrire un texte dans une langue définie, il est indispensable de connaître les symboles
nécessaires à la formation des mots et des phrases.
Pour écrire un programme en C++ les caractères suivants sont autorisés.
- les majuscules
- les minuscules
- les caractères spéciaux
- les chiffres
- les caractères invisibles (retour chariot, saut de ligne, saut de page, tabulation)
On distingue habituellement les notions suivantes :
- Les commentaires
- Les identificateurs
- Les mots réservés
- Les types primitifs
- Les variables et les constantes,
- etc.
Exemple
int main ( ) {
a=2;
b=3;
mult= a * b ;
cout << "le résultat est : " << mult;
return 0;
}
Les commentaires
Pour faciliter l’interprétation des programmes sources, il est conseillé d’y ajouter des commentaires.
Les commentaires C++ peuvent être placés partout, ils peuvent s’écrire sous la forme suivante :
/* le commentaire */
// sur la même ligne avec une instruction
a = a + 1 ; // incrémentation de la variable a
Les identificateurs
Les identificateurs nomment les objets C++ (variables, fonctions, classes etc.).
Un identificateur valide est constitué d’un ou plusieurs caractères qui peuvent être des lettres, des chiffres ou
le caractère de soulignement.
Page 10
Le premier caractère doit être constitué par une lettre ou par le caractère de soulignement. Pas d’espaces
entre les caractères d’un identificateur. Les identificateurs qui contiennent un double souligné ou bien qui
commencent par un souligné suivi par une lettre en majuscule sont réservés pour être utilisés par le système.
Exemple
N.B. Un identificateur peut-être arbitrairement très long mais certains compilateurs ne vont distinguer que
les 31 premiers caractères.
Mots clés réservés
- Un identificateur ne peut-être un mot clé réservé du langage. Les mots clés du C++ sont :
Certains de ces mots clés proviennent du langage C. D’autres ont été repris par le langage Java.
Types primitifs
Un type de donnée définit la taille de la mémoire occupée et la forme de sa mémorisation. La taille dépend du
système d’exploitation et de la version du compilateur. Pour connaître la taille d’un type, on utilise la
fonction sizeof(). Par exemple sizeof(int) indique la taille d’un type entier.
Le tableau suivant indique à titre d’exemple la taille et l’intervalle pour certains types de données très
utilisés.
Type Taille Valeurs
char 1 octet -128 à 127
unsigned char 1 octet 0 à 255
int 4 octet -32768 à 32767
unsigned int 4 octet 0 à 65535
short 2 octet -32768 à 32767
unsigned short 2 octet 0 à 65535
long 4 octet -2147483648 à + 2147483647
Page 11
unsigned long 4 octet 0 à 4294967295
float 4 octet 3.4 10-38 à 3.4 10+38
double 8 octet 1.7 10-308 à 1.7 10+308
long double 10 octet 1.2 10-4932 à 1.2 10+4932
Les types primitifs disponibles déjà en C sont utilisables en C++.
- Les données peuvent être :
1. un nombre entier,
2. un réel,
3. un booléen,
4. un caractère,
5. une chaîne de caractères.
Nombre entier - Décimal, octal ou hexadécimal.
- Un préfixe permet de préciser la base : 0X ou 0x pour un entier hexadécimal, 0 pour un octal, « rien » pour
un décimal.
- Ce nombre peut avoir aussi un suffixe, une combinaison des lettres U (ou u) et L (ou l). U pour « unsigned
» non signé et L « Long » pour long.
- Si un nombre entier est codé sur 2 bits dont le bit le plus élevé est le bit de signe, on ne peut avoir pour cette
représentation que les nombres entiers suivants : -1 (11), -0 (10), +0 (00) et 1 (01).
- Si un nombre entier est non signé, le bit le plus élevé ne sert plus le signe puisque tous les nombres sont des
entiers positifs. Ce bit va permettre de représenter encore plus de nombres. Nous aurons ainsi, toujours pour
un entier codé sur 2 bits, les nombres suivants : 0 (00), 1 (01), 2 (10) et 3 (11).
- La représentation « Long » signifie que nous allons coder les nombres en utilisant plus de précision (donc
plus de bits).
Nombre Réel - Un nombre représenté en virgule flottante et peut avoir un de ces types :
1. Float : pour une représentation en simple précision.
2. Double : pour une représentation en double précision.
3. Long double : pour une représentation à précision étendue.
Booléen
Page 12
- Une constante du type « bool » qui peut prendre les valeurs « true » pour vraie et « false » pour faux.
Caractère - Un caractère est généralement écrit entre apostrophes.
- Le type utilisé pour le représenter est « char ».
- Par exemple, le caractère « a » peut être exprimé sous l’une des formes suivantes :
'a', char (97), '\0141','\x61'. - Quelques caractères de contrôle nécessitent l’utilisation d’une forme symbolique. Cette forme est
représentée par « \ ». Par exemple '\t' signifie une tabulation, '\?' pour représenter un point d’interrogation.
- Un caractère a une valeur égale à la valeur numérique du caractère dans le code caractère de la machine. Si
le code « Ascii » est utilisé, la valeur numérique de « a » est 97 alors que celle de « A » est 65.
- Un caractère est représenté sur 1 octet. Dans ce cas, sa valeur numérique sera entre 0 et 127.
- Un caractère peut-être représenté aussi d’une manière non signée. Dans ce cas, sa valeur numérique sera
comprise entre 0 et 255. Ici, on parle d’une table « Ascii » étendue.
Chaîne de caractères - Elle est constituée d’une série de caractères.
- Elle est délimitée par les guillemets « " ».
- Les constantes chaînes de caractères sont stockées en zone de mémoire permanente.
- Elles sont considérées comme un tableau dont la taille est la longueur de la chaîne plus 1. Ce « 1 » en plus,
c’est le caractère nul « \0 » placé à la fin de la chaîne.
Déclaration et définition
- Pour pouvoir utiliser un identificateur, un compilateur doit savoir à quoi correspond cet identificateur : un
type donné, un nom de variable, un nom de fonction ou toute autre chose.
- Une déclaration informe le compilateur sur la nature exacte de l’identificateur.
- Une définition est associée à un espace mémoire, une valeur, un corps ou le contenu d’une déclaration.
- La différence entre une déclaration et une définition est que la première fournit le nom et le type de
l’identificateur alors que la seconde une vue matérielle de l’identificateur.
Les variables
Une variable est un emplacement de mémoire d’un ou de plusieurs octets qui permet de stocker des
valeurs. Chaque variable possède :
- Un type
- Une valeur
- Une adresse
- Un nom
Page 13
Déclaration d’une variable
type nom_de_variable [ = valeur ]
Exemple
int x;
x = 12 ;
Une variable possède un nom unique et doit être déclarée avant d’être utilisée.
Syntaxe :
- Pour une variable les notions de déclaration et de définition se confondent.
- Une variable peut être déclarée à n’importe quel emplacement du programme (c’est aussi le cas en Java
mais pas en C).
- Une variable peut-être initialisée au moment de sa déclaration.
- Une variable peut-être utilisée sans être préalablement initialisée (ce serait une erreur en Java).
- On peut décaler son initialisation plus loin dans le programme.
- Une variable peut-être initialisée aussi avec la valeur d’une expression.
Les constantes
Ce sont des éléments qui ne changent pas de valeur durant l’exécution du programme. Pour les déclarer on
doit utiliser le mot clé const Syntaxe de déclaration
const type nom = valeur ;
Exemple
const int x = 2 ;
Page 14
Chapitres III. Opérateurs, expressions et conversions
Expressions - Une expression est la composition d’opérateurs, de variables, de constantes, de fonctions et de parenthèses.
- Une expression retourne toujours un résultat, sa valeur.
- La valeur de l’expression a un type et, elle peut-être utilisée dans une autre expression
Dans cet exemple :
Opérateurs
Un opérateur représente une opération effectuée sur un ou deux opérandes. Le langage C++ est riche
en opérateurs. Il existe cinq types d’opérateurs :
- Les opérateurs arithmétiques
- Les opérateurs de comparaison
- Les opérateurs logiques
- Les opérateurs d’affectation
- Les opérateurs d’incrémentation et de décrémentation
Page 15
Opérateurs arithmétiques
- Le symbole « % » représente l’opérateur modulo.
- Il fournit le reste de la division entière de son premier opérande par son second.
- Remarque : la division entière n’est réalisée que sur des nombres entiers.
Opérateurs de manipulation de bits
Page 16
Opérateurs d’incrément et de décrément - Les opérateurs d’incrémentation ou décrémentation sont placés soit avant (pré) soit après (post) la variable.
- Pré : L’incrémentation/décrémentation est effectuée puis la variable est utilisée.
- Post : L’utilisation de la variable est effectuée avant l’incrémentation/décrémentation.
Exemple.
Opérateurs d’affectation - L’élément à gauche du « = » se voit affecter la valeur retournée par l’expression de droite.
- Les conversions éventuelles sont prises en considération lors de l’affectation.
a = 1, b = 0 a = 2 , b = 2 b = ++a
a = 1, b = 0 a = 0 , b = 0 b = --a
a = 1, b = 0 a = 2 , b = 1 b = a++
a = 1, b = 0 a = 0 , b = 1 b = a--
Page 17
Opérateurs relationnels et booléens - Le résultat de la comparaison de deux expressions vaut :
-false (0) si le résultat de la comparaison est FAUX.
- true (1) si le résultat de la comparaison est VRAI.
- Une expression est vraie si elle est non nulle.
- Une expression est fausse si elle est égale à zéro.
Opérateur de séquence - L’opérateur de séquence est représenté par le symbole « , ».
- Il est le moins prioritaire dans la table des opérateurs.
- Il permet d’évaluer les différentes opérations dans l’ordre.
- Dans une liste d’expressions séparées par « , », chaque expression est évaluée en premier avant de passer à
la suivante qui se trouve à sa droite.
Opérateur conditionnel - Il est appelé aussi opérateur ternaire.
- Il prend comme opérandes 3 expressions.
- La syntaxe de l’opérateur conditionnel est comme suit :
Page 18
- « expression1 » est évaluée en premier.
- Si « expression1 » est vraie alors : « expression2 » est évaluée. Le résultat est celui fourni par
«expression2»
- Si « expression1 » est fausse alors : « expression3 » est évaluée. Le résultat est fourni par « expression3 ».
Opérateur de taille - L’opérateur de taille est représenté par le mot clé réservé « sizeof ».
- Il permet de déterminer la taille en octets d’une variable ou d’un type ou d’une expression.
- Cette taille est calculée en fonction de l’architecture interne de la machine.
Conversions - Le langage C++ a deux types de conversion: implicite et explicite.
Conversions implicites
- Les conversions implicites peuvent avoir lieu dans le calcul d’une expression quand on passe directement
un argument à une fonction ou lors du retour d’une valeur par une fonction.
- Ces conversions implicites facilitent la tâche du programmeur.
- Cependant elles risquent d’être potentiellement dangereuses si l’on ne garde pas un œil ouvert.
- En effet, elles peuvent générer des bogues lors de l’exécution d’un programme. Des bogues qui sont parfois
difficiles à cerner pour le commun des mortels !
- Les règles de conversion sont comme suit :
o Si l’opérande est du type « char », « short » ou « bool » elle est convertie en « int ».
o Si l’opérande est un nombre entier tellement grand que l’on ne peut pas représenter par un « int », il
sera représenté par un « unsigned int »
o Après ces deux premières étapes de conversion, si une expression contient un ensemble de types
différents, la hiérarchie à suivre lors de la conversion est comme suit
� « int » < « unsigned » < « long » < « unsigned long » < « float »< « double » < « long
double».
Page 19
� L’opérande, ayant un type moins élevé dans la hiérarchie, est promue à un type plus élevé et
l’expression récupère ce type.
Conversions explicites - On peut demander explicitement une conversion d’un opérande dans un type désiré.
- Cette opération s’appelle « casting » ou « transtypage ».
- Les règles de forçage de conversion de type du langage C peuvent être utilisées aussi en C++.
- 4 nouveaux opérateurs ont été introduits en C++, pour forcer la conversion de type.
Page 20
Chapitre IV : Entrée/Sorties en C++ La bibliothèque iostream offre deux opérateurs surchargés de manière appropriée pour les flux:
• L’opérateur d'insertion << (écriture)
• L’opérateur d'extraction >> (lecture)
1- le flux de sortie cout
Sortir des données à l’aide d’un flux n’est pas très difficile. La syntaxe s’écrit sous la forme :
cout << données;
cout : le flux de sortie
<< : L’opérateur de transfert
données : les données a afficher qui sont de type ( int, char, char *, float )
•••• chaînage
Si vous avez plusieurs variables a afficher. Vous pouvez utiliser autant d’instructions de sortie
que de variables à afficher, ou vous pouvez l’écrire dans une même instruction. Par exemple
cout << 123456;
cout << ‘\n’;
cout << 1.23456;
ou on peut les chaîner dans une même instruction
cout << 123456 << ‘\n’ << 1.23456;
Mise en forme de la sortie Vous pouvez choisir le format des sorties que vous voulez à l’aide des fonctions prédéfinies de la
bibliothèque iostream, appelées manipulateurs. Il y’a deux types de manipulateurs, manipulateurs
avec paramètres et sans paramètres.
Remarque : pour utiliser un manipulateur, il suffit d’écrire son nom avant la valeur à afficher en ajoutant
comme séparateur un nouvel exemplaire de l’opérateur de transfert (<<).
Page 21
Exemple
2. Le flux d’entrée cin
Le flux d’entrée cin conduit les données tapées au clavier vers votre programme (en mémoire). Le cin
commence la lecture après la touche Enter (le retour chariot).
Syntaxe : cin >> variable
cin : mot clé qui le nom du flux d’entre
>> : opérateur de transfert
variable : nom de la case mémoire qui vas recevoir la valeur entrée.
Chaînage Si vous avez plusieurs variables a lire. Vous pouvez utiliser autant d’instructions de lecture que de variables a
lire, ou vous pouvez l’écrire dans une même instruction. Par exemple
cin >> i;
cin >> c;
cin >> d; ou on peut les chaîner dans une même instruction : cin >> i >> c >> d;
il suffit de séparer les différentes saisies, par des caractères d’espacement :espace, tabulation, ou saut de
ligne ( Enter ).
Manipulateur
Formatage
Librairie
dec Base de numérotation décimale iostream
Oct Base de numérotation octale iostream
Hex Base de numérotation hexadécimale iostream
setprecision(nombre) Précision en virgule flottante iomanip
setw(nombre) Largeur minimale d’affichage iomanip
setfill(caractere) Le caractère de remplissage iomanip
Page 22
Chapitre V : Structures de contrôle
Généralités
Maîtrisant la construction d'expressions, nous pouvons aborder les instructions. Une instruction peut
revêtir différentes formes. On distingue les instructions simples, les instructions de saut, les instructions
composées, les instructions alternatives et les instructions répétitives.
Instructions simples
Pour former une instruction simple, il suffit de suffixer une expression par un point-virgule ";". Les
exemples suivants sont des instructions simples en C++ :
X = X + Y;
X--;
X -= Y, Y++;
Instructions de saut
Une instruction de saut provoque une rupture inconditionnelle dans l'exécution séquentielle des
instructions d'un programme et ont leur utilité dans les structures de contrôle, nous y reviendrons plus
tard.
Instructions composées
Les instructions composées, encore appelées blocs, regroupent des déclarations et des instructions et
sont délimitées par des accolades "{" et "}". La syntaxe exige que les déclarations soient regroupées au
début du bloc, elles ne peuvent donc être mélangées avec les instructions du bloc.
Exemple
{
double pi = 3.1415;
circonference = 2 * pi * rayon;
}
Instructions alternatives
Les instructions de contrôle sont un des éléments qui font que le langage C++ appartient à la catégorie
des langages de programmation de haut niveau.
L’instruction IF simple :
L'expression est évaluée. Si elle est différente de zéro (en d'autres termes si elle est "vraie"),
l'instruction ou le bloc d’instructions après le if est exécuté.
1) l’algorithme:
si (expression) instruction;
ou bien
Page 23
si (expression)
{
instruction1;
instruction2;
.
.
.
instructionn;
}
2) le programme en C++
IF (expression) instruction; ou bien
if (expression)
{
instruction1;
instruction2;
.
.
instructionn;
}
L’instruction If … else :
L'expression est évaluée. Si elle est différente de zéro (en d'autres termes si elle est "vraie"),
l'instruction instruction1 est exécutée, sinon, l'instruction instruction2 est exécutée.
l’algorithme:
si (expression)
{ instruction1;
instruction2;
.
.
.
instructionn;
}
sinon
{
instruction1;
instruction2;
.
.
.
instructionn;
}
Page 24
Le programme en C++
if (expression)
{
instruction1;
instruction2;
.
.
.
instructionn;
}
else
{
instruction1;
instruction2;
.
.
.
instructionn;
}
L'exemple suivant illustre l'alternative simple :
if (delta >= 0)
{ x1 = (-b + sqrt (delta)) / (2 * a);
x2 = (-b - sqrt (delta)) / (2 * a);
cout <<"solutions : =<< x1 << x2 << endl;
}
else
cout <<"pas de solution\n";
Les tests imbriqués If … else if …. else :
Parfois, on a des cas plus nuancés à traiter. On peut alors recourir aux alternatives imbriquées qui ont la
forme :
algorithme
si (expression1)
{ instructions;
…
} sinon si (expressioni)
{ instructions;
…
}
sinon { instruction1;
Page 25
…
}
programme
if (expression1)
{ instructions;
… } else if (expressioni)
{ instructions;
…
}
else
{ instruction1;
…
}
exemple :
if (delta > 0)
{ x1 = (-b + sqrt (delta)) / (2 * a);
x2 = (-b - sqrt (delta)) / (2 * a);
cout <<"solutions =" << x1 << x2 << endl;
} else if (delta == 0)
{ x = (-b + sqrt (delta)) / (2 * a);
cout <<"solution x = " << x << endl;
} else cout <<"pas de solution\n";
Il ne faut pas confondre entre l’exemple suivant :
if (delta > 0)
{ x1 = (-b + sqrt (delta)) / (2 * a);
x2 = (-b - sqrt (delta)) / (2 * a);
cout <<"solutions = " << x1 << x2 << endl;
} if (0 == delta)
{ x = (-b + sqrt (delta)) / (2 * a);
cout <<"solution x = " << x << endl;
} else cout << "pas de solution\n";
Page 26
L’instruction switch
Le dernier type d'alternative que l'on trouve en C++ est le choix multiple, encore appelé instruction
d'aiguillage. Elle opère un choix parmi un nombre quelconque de propositions; elle de ce point de vue
comparable à une instruction if .. else imbriquée. Chaque bloc doit se terminer par un break afin de
quitter le bloc.
Forme algorithmique
Cas ou (expression)
{
cas valeur1 :
bloc1; [break;]
cas valeur2 :
bloc2; [break;]
...
...
...
cas valeurn :
blocn; [break;]
[default :
bloc default;]
}
Programmation
switch (expression)
{
case valeur1 :
bloc1; [break;]
case valeur2 :
bloc2; [break;] ...
...
...
case valeurn :
blocn; [break;]
[default :
bloc default;]
}
Remarque
• L'expression doit être de type caractère ou entier.
• Toutes les expressions constantes associées aux étiquettes case doivent être de type caractère ou
entier et doivent avoir des valeurs différentes.
Page 27
• Il ne peut y avoir qu'une seule instruction étiquetée default
• Si un choix multiple est imbriqué dans un autre, ses instructions étiquetées case peuvent bien sûr
utiliser les mêmes valeurs constantes que le choix multiple englobant et il peut bien évidemment avoir
sa propre instruction étiquetée default.
• Le choix multiple provoque l'évaluation de l'expression et le saut à l'instruction étiquetée case dont la
valeur constante associée est identique à celle de l'expression évaluée.
• Si aucune valeur constante ne correspond, le choix multiple provoque le saut à l'instruction étiquetée
default.
• S'il n'y a pas d'instruction étiquetée dans le choix multiple, il est sans effet.
• Lorsque l'instruction associée à l'étiquette case a été exécutée, l'exécution continue avec l'instruction
qui suit cette instruction étiquetée.
• Pour sortir du bloc on utilise l'instruction break qui provoque un saut à l'extérieur de la structure de
contrôle. L'exemple suivant illustre ceci :
switch (sexe)
{ case 'm' : cout <<"Bonjour Monsieur.";
break;
case 'f' : cout <<"Bonjour Madame.";
break;
default : cout <<"Bonjour.";
}
Cas multiples
Une étiquette case ne doit pas obligatoirement être suivie d`instructions, vous pouvez donc attribuer les
mêmes instructions a plusieurs étiquettes.
Syntaxes :
switch (expression)
{
case valeur1 :
case valeur2 :
case valeur3 :
bloc d’instruction; [break;]
case valeur4 :
bloc4; [break;]
[default :
bloc default;]
}
Page 28
Exemple :
switch (chiffre)
{
case 0 :
case 2 :
case 4 :
case 6 :
case 8 :
cout <<‘’le nombre est pair \n’’;
break;
case 1 :
case 3 :
case 5 :
case 7 :
case 9 :
cout <<‘’le nombre est impair \n’’; }
Instructions répétitives
La nécessité d’exécuter certaines étapes de travail plusieurs fois à la suite s’impose très souvent lors du
développement d’un programme.
Par exemple on veut écrire un programme qui compte jusqu'à 100 et affiche chaque valeur comptée.
• soit on écrit 100 instructions l’une à la suite de l’autre pour afficher chaque valeur comptée.
• Soit on écrit une seule instruction qui affiche à l’intérieur d’une structure répétitive ou boucle.
Il existe trois structures répétitives en C++ :
1-) while (expression logique) instruction;
2-) do instruction; while (expression logique)
3-) for (initialisation; expression logique; reinitialisation)
instruction;
Dans toutes ces structures, l'instruction, appelée corps de boucle, est exécutée jusqu'à ce que l'expression
logique, appelée condition de maintien dans la boucle, devienne vraie.
Les instructions while et do while correspondent tout à fait à des constructions que l'on peut trouver
dans d'autres langages. L'instruction for cependant est un peu particulière.
1-) l’instruction while
C’est une instruction qui répète un certain travail selon une condition.L'instruction while évalue d'abord
l'expression logique avant d'exécuter l'instruction. L'exemple suivant pourrait servir au calcul de la
factorielle d'un entier positif n :
Cin >> n;
while ( n > 0 ) fact = fact * n--;
Page 29
1) l’algorithme
tant que ( expression logique )
{
instruction (s);
}
2) programme
while ( expressiom logique )
{
instruction (s);
}
Exemple.
2-) l’instruction do … while
l'instruction do … while, par contre, exécute d'abord l'instruction avant d'évaluer l'expression logique.
L'exemple suivant lit une séquence d'entiers jusqu'au premier entier négatif :
Do
{
cout <<" donnez une valeur " << endl;
cin >> n;
} while ( n >= 0 );
Page 30
1) l’algorithme
faire
{
instruction (s);
} tant que ( condition logique);
2) programme
do
{
instruction (s);
} while ( expressiom logique );
Exemple
Som = 0;
I = 1;
Do
{
som += i;
i++;
} while ( n >= 0 );
cout <<" la somme totale = " << som << endl;
3-) l’instruction for
Enfin, comme nous l'avons signalé, l'instruction for est assez particulière. La sémantique du for est
équivalente à celle de la séquence d'instructions suivante :
for (initialisation; expr. logique; reinitialisation)
{ instruction(s);
}
Page 31
1) l’algorithme
pour (initialisation; expr. logique; reinitialisation)
{ instruction(s);
}
2) programme
for (initialisation; expr. logique; reinitialisation)
{ instruction(s);
}
Exemple
for (somme = 0, i = 1; i <= 100; i++)
{
cin >> n;
somme += n;
}
Remarque
- En C++, on peut déclarer des variables dans la partie « initialisation ».
- La visibilité de ces variables sera le bloc « for » délimité par « { » « } ».
4-) instructions de saut
L'instruction associée aux structures répétitives peut contenir les instructions de saut break et continue.
Le break, comme dans le cas du choix multiple, provoque tout simplement un saut à l'extérieur de la
structure répétitive tant disque le continue provoque un saut à la fin de l'instruction.
Le morceau de programme suivant cumule au maximum 100 entiers qu'on a lus sur le fichier standard
d'entrée jusqu'au moment où l'on lit un entier négatif ou nul auquel cas on arrête le traitement répétitif
prématurément :
for (somme = 0, i = 1; i <= 100; i++)
{
Page 32
cin >> n;
if (n <= 0) continue;
somme += n;
}
Dans le morceau de programme suivant, on fait presque la même chose. La seule différence est qu'on
continue le traitement répétitif mais sans cumuler la valeur négative ou nulle:
for (somme = 0, i = 1; i <= 100; i++)
{
cin >> n;
if (n < =0) continue;
somme += n;
}
Portée (visibilité) des variables
En C++ il y a plusieurs catégories de visibilité : fichier, fonction, bloc, classe, prototype de la fonction,
espace de nom.
- Visibilité au niveau du fichier : la portée de la variable s’étend de l’endroit où elle a été déclarée dans le
fichier jusqu’à la fin de ce fichier. Cette possibilité n’est offerte que dans les langages C et C++ puisque Java
est un langage pur objet. La variable est appelée dans ce cas « variable globale » car sa portée est globale.
- Visibilité bloc : la durée de vie d’une variable est celle du bloc où elle a été déclarée sauf dans le cas d’une
variable globale.
Exemple 1.
Exemple 2. Attention aussi aux déclarations dans les instructions de contrôle
Page 33
Exemple 3.
En sortie:
i du main vaut avant: 500
i boucle vaut: 0
i du main vaut après: 500
Il est impossible d'afficher la valeur de la variable i de la méthode main à partir de la boucle for.
Page 34
Exemple 4.
En sortie:
i du main vaut avant: 500
i en dehors du main vaut avant: 1000
i boucle vaut: 0
i du main vaut apres: 500
i en dehors du main vaut apres: 1000
- Le symbole « :: » désigne l'opérateur unaire de résolution de portée. On l’appelle aussi l'opérateur de
visibilité (scope qualifier operator). Dans cet exemple, « :: » fait référence à l'espace de nom anonyme (qui ne
porte pas de nom).
Page 35
Chapitre VI. Fonctions
Généralités
Pour décomposer un programme complexe en plusieurs programmes plus élémentaires, on a le plus
souvent recours à la notion de sous-routine ou fonction. Les fonctions C/C++ sont des sections de
programme qui remplissent une tache partielle du programme global. Chacune de ces fonctions possède
un nom par lequel il sera facile de lancer son exécution. Ce chapitre se propose de discuter les
problèmes du passage des paramètres aux fonctions en C/C++ et du retour d'un résultat vers la fonction
appelante.
1-Déclaration des fonctions
Avant d’utiliser une fonction il faut la déclarer. Une déclaration de fonction est instruction qui contient
des informations sur les caractéristiques de cette fonction. Il s’agit du nom de la fonction, de la
description de ses paramètres et de sa valeur de retour et elle se termine par un point-virgule. La
déclaration de fonction est la définition de son prototype (entête).
Syntaxe
Type_de_valeur_de_retour nom_de_la_fonction ( [ type1 nom1 ], [ type2 nom2 ], … , [ typen
nomn ] ); Remarque: Ce qui figure entre crochets est facultatif.
Exemple
int somme( int a, int b);
void somme( int a, int b );
2-Définition des fonctions
La définition se fait comme suit :
type_de_retour nom ( [ type1 nom1 ], [ type2 nom2 ], … , [ typen nomn ] )
{
les instructions;
}
Page 36
Exemple
void somme ( int a, int b)
{
int s; s = a + b;
cout<< “somme est : “<<s<<endl;
}
3-Appel de fonction
La syntaxe d’appel de fonction, est relativement simple : elle se constitue du nom de la fonction et de la
liste des paramètres qui lui sont transmis pour traitement.
Syntaxe :
Nom_de_la_fonction ( [par1], [par2], … , [parn] );
Exemple. Somme( 5, 4 );
Remarque. - Le prototype est facultatif en C mais OBLIGATOIRE en C++,
- Une fonction doit être déclarée avant d'être appelée.
Page 37
- Les deux précédentes écritures reviennent à dire la même chose.
- Le compilateur dans tous les cas ignore le nom des variables dans la déclaration d’une fonction.
-L’appel d’une fonction se fait en donnant son nom puis les valeurs de ses paramètres entre parenthèses.
- On peut également écrire le prototype et définition en même temps
4- valeur de retour d’une fonction : return
4-1 fonction sans valeur de retour
La sortie d'une fonction est effectuée avec l'instruction de saut return. Dans le cas des fonctions sans
résultat, c'est-à-dire des fonctions de type void, l'instruction return est utilisée isolément (on pourra
l’omettre) comme dans l'exemple suivant :
void somme(int a, int b)
{
int s;
s=a + b;
cout<<"la somme de a et b : "<<endl;
[return;]
}
4-2 fonction avec valeur de retour Dans le cas d'une fonction avec résultat, l'instruction return s'utilise avec une expression. Le type de
cette expression doit nécessairement correspondre au type déclaré de la fonction. Ceci est illustré par la
fonction suivante qui calcule la somme de deux valeurs int :
int somme( int a, int b)
{
Page 38
int s;
s = a + b;
return s;
}
On peut déclarer une fonction sans spécifier le type du résultat. Le type par défaut est le type int.
4-3 paramètres par défaut Le nombre de paramètres réels ne doit obligatoirement correspondre à celui des paramètres formels, il peut
être plus petit ou plus grand. Ici nous examinons les fonctions auxquelles il est possible de transmettre
moins de paramètres réels qu`elle ne dispose de paramètres formels.
Le C/C++ nous permet de donner une valeur par défaut à un paramètre formel s’il n’a pas de paramètre
réel correspondant. La spécification des paramètres par défaut se réalise avant l’appel de la fonction, dans
la liste des paramètres formels, donc dans l’en-tête de la fonction.
Exemple
int somme( int a = 2, int b = 1)
{
int s;
s = a + b;
return s;
}
/****** l’appel ******/
somme ( 5, 6 ); ou somme ( ); ou somme( 5 );
4-1 Fonction sans paramètres (arguments) - Une fonction sans arguments restera sans type
Remarque.
- En C par défaut retourne un « int » si on l’ignore.
- En C++ déclaration du type de la valeur retournée est OBLIGATOIRE,
5. Surdéfinition de fonctions
- Un nom (de fonction, d'opérateur, etc.) est surdéfini s'il désigne plus d'une chose à la fois.
- 5/2 division entière (2, et le reste est perdu)
- 5.0/2.0 division réelle (2.5)
- L’opérateur « / » a un double rôle: la division des nombres entiers et des nombres réels.
- En C++, on peut définir différentes fonctions ayant le même nom mais le nombre et le type de paramètres
sont différents.
Page 39
- Le compilateur recherche la « meilleure correspondance » possible.
- S'il y a plusieurs arguments, le compilateur essaye chacun séparément.
- Le compilateur signale une erreur de compilation si aucune fonction ne convient ou bien si plusieurs
fonctions conviennent. Donc, il y a plusieurs choix possibles (ambiguïté) dans celles-ci.
Page 40
- Pour un seul argument, le compilateur essaie dans l'ordre:
- Correspondance exacte de types.
- Promotion numérique
6. Fonctions inline (en ligne)
#define est utilisé pour la substitution de texte.
- Une autre utilité du #define est la définition de macros.
- Une macro est une pseudo fonction substituée dans tout le programme pendant le prétraitement
(préprocesseur) avant la compilation.
- Elle évite le coût d'un appel de fonction en contrepartie le code exécutable devient plus volumineux.
Page 41
Chapitre VII. Tableaux & pointeurs
Généralités
Ce chapitre décrit les mécanismes de composition de types dont le programmeur dispose en C/C++.
Nous discutons plus particulièrement les tableaux, les chaines de caractères et les pointeurs.
Nous avons vu qu'un développeur C/C++ était amené à manipuler des objets de type caractère, entier
ou réel dans ses programmes. Ces types sont des types prédéfinis du langage. Le langage C/C++ intègre
cependant des mécanismes offrant au développeur la possibilité de définir de nouveaux types, sur base
des types prédéfinis. Ces nouveaux types doivent permettre au programmeur de mieux rendre compte,
dans son programme, du problème concret qu'il a à résoudre.
1-Tableaux unidimensionnel
Un deuxième mécanisme de composition de types est la définition de tableaux. Un tableau est un
ensemble fini d'éléments de même type pour lesquels un espace contigu est alloué en mémoire centrale.
La taille d’un tableau (en octects) depend du type des objets destinés à y etre stockés.
1-2- Déclaration d’un tableau unidimensionnel
Pour déclarer un tableau unidimensionnel en C/C++, on utilise les crochets "[" et "]" et on indique le
type des éléments du tableau, son nom et ainsi que sa taille.
Par exemple, dans les déclarations suivantes :
Int tab [ 6 ];
On a déclaré un tableau de 6 éléments de type entier. Le premier élément du tableau est désigné par
tab[0], le deuxieme par tab[1] et ainsi de suite. La taille du tableau est 24 octets.
Tab[0] tab[1] tab[2] tab[3] tab[4] tab[5]
1-3- initialisation du tableau
Au moment de la déclaration d’un tableau on peut affecter des valeurs au éléments de ce dernier. On
indique à cet éffet les valeurs initiales sous forme d’une liste ( que l’on place entre accolades ), séparées
par des virgules. Selon la regle suivante:
Page 42
Type nom_du_tableau [ nombre d’élements ] = { val1, val2, val3,…, valn };
Exemple.
Int note [ 10 ] = { 15, 17, 09, 10, 14, 19, 16, 14, 17, 12 };
15 17 09 10 14 19 16 14 17 12
1-4- Accés aux éléments d’un tableau
Pour manipuler les éléments d’un tableau, un procédé permettant d’accéder à n’importe quel élément de
tableau est nécessaire qui l’indexation.
Pour distinguer les différents éléments du tableau en vue d’y accéder, on leur attribue des dénominations
uniques à l’aide du nom du tableau et d’un index créées selon le modele suivant:
Nom_tableau [ index ]
L’index doit etre une expression à nombres entiers placée entre crochets. L’indexation commence
toujours à 0.
Exemple:
Note [0], Note [1], Note [2], Note [3], Note [4], …. , Note [8], Note [9]
1-5- adresse d’un élément du tableau
Au niveau de la mémoire centrale chaque élément du tableau est stoché dans une adresse fixe. Supposon
que l’adresse du début du tableau note est 3188. l’adresse du 3eme élément est notéé comme :
& note [ 2 ] = 3188 + 2 * 4 = 3188 + 8 = 3196
en général l’adresse d’un élément n est :
& note [n] = adresse du debut + n * taille du type de données
Exemple 1: soit un programme qui déclare un tableau de 10 éléments de type entier, l’initialise et
faire la somme des éléments du tableau.
#include < iostream.h >
void main ( )
{
int tab [10] = { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9};
int I, total = 0 ;
for ( I = 0; I<10; I++ )
Page 43
total += tab[I];
}
Exemple 2: soit un programme qui déclare un tableau de 10 éléments de type entier, le remplit et
l’affiche par la suite.
#include < iostream.h >
void main ( )
{
float tab [10] ;
int I ;
for ( I = 0; I<10; I++ )
cins >> tab[I];
/** l<affichage du tableau ***/
for ( I = 0; I<10; I++ )
cout << tab[I];
}
1-6)- Le tri des éléments du tableau
le tri des éléments de tableau s’effectue selon la méthode de base appelée algorithme de tri ou tri à
bulles.
Elle consiste à parcourir le tableau concerné plusieurs fois du début à la fin de la partie non triée et à
chaque parcours de déplacer à la premiere case non triée le plus petit élément ( pour un ordre de tri
croissant ) ou le plus grand élément ( pour un ordre de tri décroissant ).
Exemple
#include < iostream.h >
void main ( )
{
float tab [10] ;
int I ,j;
/************** le remplissage du tableau *************/
for ( I = 0; I<10; I++ )
cin >> tab[I];
/***************** le tri du tableau ******************/
for ( I = 0; I<9; I++ )
for ( j = I+1; j<10; j++ )
Page 44
if ( tab[ I ] > tab[ j ])
{
temp = tab[ I ];
tab[ I ] = tab[ j ];
tab[ j ] = temp;
}
/*********************** l’ affichage du tableau ****************/
for ( I = 0; I<10; I++ )
cout << tab[I];
}
2-Tableaux bidimensionnel
Un tableau à deux dimensions est un ensemble fini d'éléments de même type pour lesquels un espace
contigu est alloué en mémoire centrale. Il est considéré comme un tableau à une seule dimension dont
chaque case est un tableau à une seule dimension.
La taille d’un tableau à deux dimensions (en octects) depend du type des objets destinés à y etre
stockés.
2-2- Déclaration d’un tableau bidimensionnel
Pour déclarer un tableau bidimensionnel en C/C++, on utilise les crochets "[" et "]" et on indique le
type des éléments du tableau, son nom et ainsi que sa le nombre de lignes et le nombre de colonnes.
Par exemple, dans les déclarations suivantes :
Int tab [ 4 ][ 6 ];
On a déclaré un tableau de 4 lignes et de 6 colonnes de type entier. Le premier élément du tableau est
désigné par tab[ 0 ][ 0 ], le deuxieme par tab[ 0 ][ 1 ] et ainsi de suite. La taille du tableau est ( 4*6*4
= 96) octets.
2-3- initialisation du tableau
Au moment de la déclaration d’un tableau on peut affecter des valeurs au éléments de ce dernier. On
indique à cet éffet les valeurs initiales sous forme d’une serie de liste ( que l’on place entre accolades ),
séparées par des virgules. Selon la regle suivante:
Type nom_du_tableau [ lignes ][ colonnes ] = {{ val01, val2, …, val0n },
{val10,val12,…,val1n },
….. {valm0, valm1,…, valmn} };
Page 45
Exemple:
Int note [ 4 ][ 6 ] = { {1, 2, 3, 4, 5, 6},{ 7, 8, 9, 10, 11, 12},
{ 13, 14, 15, 16, 17, 18 },{ 19, 20, 21, 22, 23, 24}} ;
2-4- Accés aux éléments d’un tableau à deux dimensions
Pour manipuler les éléments d’un tableau à deux dimensions, un procédé permettant d’accéder à
n’importe quel élément de tableau est nécessaire qui est l’indexation.
Pour distinguer les différents éléments du tableau en vue d’y accéder, on leur attribue des dénominations
uniques à l’aide du nom du tableau, le numéro de ligne et le numéro de colonne selon le modele
suivant:
Nom_tableau [ ligne ] [ colonne ];
Exemple: int Note [4 ] [ 6 ];
Note [0][0], Note [0][1], Note[0] [2], Note[0] [3], Note[0] [4], Note [0][5]
Note [1][0], Note [1][1], Note[1] [2], Note[1] [3], Note[1] [4], Note [1][5]
Note [2][0], Note [2][1], Note[2] [2], Note[2] [3], Note[2] [4], Note [2][5]
Note [3][0], Note [3][1], Note[3] [2], Note[3] [3], Note[3] [4], Note [2][5]
1-5- adresse d’un élément du tableau
Au niveau de la mémoire centrale chaque élément du tableau est stoché dans une adresse fixe. Supposon
que l’adresse du début du tableau note est 3188. l’adresse du 3ème élément est notéé comme :
& note [ 2 ][3] = 3188+2*6*4 + 3 * 4 = 3188 +48+12 = 3248
en général l’adresse d’un élément n est :
& note [n][m] = adresse du debut + n*m * taille du type + m*taille du type
Exemple 1: soit un programme qui déclare un tableau de 4 lignes et de 6 colonnes de type float, le
remplit et l’affiche par la suite.
#include < iostream.h >
void main ( )
{
float tab [ 4 ][ 6 ] ;
Page 46
int l ,c;
for ( l = 0; l<4; l++ )
for ( c = 0; c<6; c++ )
cin >> tab[ l ][ c ];
/** l<affichage du tableau ***/
for ( l = 0; l<4; l++ )
for ( c = 0; c<6; c++ )
cout << tab[ l ] [c ] ;
}
3- les chaines de caracteres
3-1) Definition
Avant d'exposer les fonctions sur les chaînes de caractères en C, il faut tout d'abord expliciter la notion
de chaîne de caractères.
Une chaîne de caractères C/C++ est un tableau unidimensionnel de caractères. Par convention, la fin de
la chaîne de caractères est indiquée par le caractère nul '\0'. Par conséquent, une chaîne de caractères
occupe en mémoire un espace correspondant au nombre de caractères significatifs de la chaîne plus un.
Une chaîne de caractères constante est délimitée par des doubles quotes et peut contenir n'importe quel
caractère sauf le caractère nul, par exemple :
"Programmeur en C/C++"
qui occupera en mémoire 21 octets, si un caractère est codé sur un octet.
Il revient au programmeur de prévoir la place nécessaire pour représenter une chaîne de caractères.
3-2) Declaration d’une chaine de caracteres
La déclaration d'une chaîne de caractères pourrait notamment se faire de la façon suivante :
char Chaine[100] = "Programmeur en C/C++";
Remarque
Page 47
On a déclaré un une chaine de caracteres de 100 éléments de type char. Le premier élément de la
chaine est désigné par chaine[0], le deuxieme par chaine [1] et ainsi de suite.
……… \0
chaine [0] chaine [1] chaine [2] ……. chaine [99]
3-4) Fonctions prédéfinies
Le langage C intègre des fonctions prédéfinies qui répondent à des besoins divers. Dans cette section,
nous allons en exposer quelques-unes qui nous semblent parmi les plus importantes. Nous ne serons pas
exhaustifs, le lecteur pourra se rapporter aux ouvrages de référence mentionnés dans la bibliogrphie
pour plus de détails. Le but de cette partie n'est pas d'être exhaustif au niveau des fonctions prédéfinies
du langage C. Ceci dépasserait le cadre de ce cours. Nous allons nous limiter aux fonctions essentielles.
Fonctions sur les chaînes de caractères
La fonction strcpy permet de copier une chaîne source dans une chaîne destination. Son entête est la
suivante en C :
char *strcpy (char *destination, const char *source);
Cette fonction copie les caractères de la chaîne source dans la chaîne destination, y compris le caractère
nul. elle retourne destination. destination doit être assez grand pour pouvoir contenir tous les caractères
de source, aucune vérification n'étant effectuée. De plus, si les deux chaînes se rec ouvrent, le
comportement de la fonction est indéterminé.
On aurait pu initialiser le tableau jeSuisUneChaine déclaré précédemment comme suit :
strcpy (jeSuisUneChaine, "Programmer en C");
Il existe une version plus prudente de cette fonction, la fonction strncpy qui copie également une chaîne
source dans une chaîne destination mais avec un maximum de n caractères. Son prototype est le
suivant :
char *strncpy (char *destination, const char *source, size_t n);
Page 48
le type size_t étant un type défini dans le fichier string.h. La fonction copie n caractères de source vers
destination. La copie s'arrête après n caractères ou lorsqu'un caractère nul est trouvé dans la chaîne
source. Si n caractères sont copiés, aucun caractère nul n'est ajouté à destination. Si source ne contient
pas n caractères, la fonction remplit destination avec des caractères nuls. destination doit être assez
grand pour pouvoir contenir n caractères, aucune vérification n'étant effectuée. Si les deux chaînes se
recouvrent, le comportement de la fonction est indéterminé.
Les fonctions strcat et strncat permettent de concaténer des chaînes de caractères.
L'entête de la fonction strcat est la suivante :
char *strcat (char *destination, const char *source);
La fonction copie la chaîne source à la suite de la chaîne destination y compris le caractère nul. Le
caractère nul de la chaîne destination originale est effacé par le premier caractère de la chaîne source.
destination doit être assez grand pour pouvoir contenir tous les caractères de destination et source,
aucune vérification n'étant effectuée. De plus, si les deux chaînes se recouvrent, le comportement de la
fonction est indéterminé.
La fonction ANSI strncat copie n caractères de la chaîne source derrière la chaîne Destination :
Char *strncat (char *destination, const char *source, size_t n);
La copie s'arrête après n caractères ou lorsqu'un caractère nul est trouvé dans la chaîne source. Le
caractère nul de la chaîne destination originale est effacé par le premier caractère de la chaîne source.
strncat ajoute toujours un caractère nul derrière la chaîne concaténée. Par conséquent, destination doit
être assez grand pour pouvoir contenir tous les caractères de destination plus n+1 caractères, aucune
vérification n'étant effectuée. Elle retourne destination.
Les fonctions strcmp et strncmp permettent de comparer des chaînes de caractères.
L'entête de la fonction strcmp est la suivante :
int strcmp (const char *chaine1, const char *chaine2);
La fonction compare caractère par caractère la chaîne chaine1 à la chaîne chaine2. La comparaison
s'arrête lorsque la fonction trouve une différence entre les deux chaînes ou lorsqu'elle est arrivée à la fin
des deux chaînes. Le résultat est négatif lorsque la fonction trouve une différence et que, dans la paire de
caractères différents, le caractère de chaine1 est inférieur au caractère de chaine2. Le résultat est positif
lorsque la fonction trouve une différence et que, dans la paire de caractères différents, le caractère de
Page 49
chaine1 est supérieur au caractère de chaine2. Si la fonction ne détecte pas de différences entre les deux
chaînes, le résultat vaut zéro.
La fonction ANSI strncmp procède à la même comparaison, mais sur un maximum de n caractères. Son
prototype est le suivant :
int strncmp (char *chaine1, char *chaine2, size_t n);
La fonction strlen fournit la longueur d'une chaîne de caractères.
Son prototype s'écrit :
size_t strlen (const char *chaine);
La fonction retourne le nombre de caractères significatifs de chaîne sans compter le caractère nul.
La fonction strchr et strrchr
char *strchr (const char *chaine, int caractere);
char *strrchr (const char *chaine, int caractere);
La function strchr recherchent la première occurrence d'un caractère dans une chaîne de caractères, le
caractère nul inclu. Elles retournent un pointeur sur le caractère trouvé en cas de succès, sinon, elles
retournent un pointeur NULL.
La fonction strrchr recherchent la dernière occurrence d'un caractère dans une chaîne de caractères.
Elles retournent un pointeur sur le caractère trouvé en cas de succès, sinon, elles retournent un pointeur
NULL.
3-5. Autres fonctions
Signalons encore l'existence de fonctions de manipulation de caractères. Pour les utiliser, il faut inclure
ctype.h en début de texte source :
#include <ctype.h>
Nous nous contenterons de les énumérer :
• isalnum vérifie si le caractère est un caractère alphanumérique (une lettre ou un chiffre).
• isalpha vérifie si le caractère est un caractère alphabétique (une lettre).
• iscntrl vérifie si le caractère est un caractère de contrôle (un caractère non imprimable).
Page 50
• isdigit vérifie si le caractère est un chiffre.
• isgraph vérifie si le caractère est un caractère imprimable (à l'exception du caractère blanc).
• islower vérifie si le caractère est une lettre minuscule.
• isprint vérifie si le caractère est un caractère imprimable (y compris le caractère blanc).
• ispunct vérifie si le caractère est un caractère de ponctuation (tout caractère imprimable qui n'est
pas un caractère alphanumérique, à l'exception du caractère blanc).
• isspace vérifie si le caractère est un caractère d'espacement (blanc, saut à la page, saut à la ligne,
retour chariot, tabulation horizontale, tabulation verticale).
• isupper vérifie si le caractère est une lettre majuscule.
• isxdigit vérifie si le caractère est un chiffre hexadécimal.
• tolower convertit le caractère en minuscule.
• toupper convertit le caractère en majuscule.
Toutes ces fonctions prennent en paramètre un entier et retournent un entier. Les fonctions de test
retournent zéro si le test est faux, une valeur différente de zéro sinon. Illustrons cela par un exemple :
if (isalnum(caractere))
printf("caractere alphanumerique\n");
4. Pointeurs
Les pointeurs constituent un premier mécanisme de composition de types.
Une variable manipulée dans un programme est stockée quelque part en mémoire centrale. Cette
mémoire est un espace constitué d'éléments appelés octets ou encore "bytes". Chaque octet peut être
référencé individuellement, étant identifié de façon univoque par un numéro qu'on appelle son adresse.
Pour retrouver une variable stockée en mémoire, il suffit donc de connaître son adresse ou plus
précisément l'adresse de l'octet ou elle est stockée (si c'est une variable qui recouvre plusieurs octets, il
suffira de connaître l'adresse du premier d'entre eux pour la retrouver). Comme ceci n'est pas un moyen
facile pour faire référence à des variables, on utilise la plupart du temps des identificateurs dans les
programmes et on laisse au compilateur le soin de faire le lien entre le nom d'une variable et l'endroit où
elle est stockée en mémoire. Toutefois, pour des raisons diverses, dont quelques-unes seront exposées
ultérieurement dans le cours, il peut parfois être intéressant d'utiliser quand-même l'adresse d'une
variable pour y faire référence. L'adresse de cette variable devient ainsi une valeur qu'on manipule dans
un programme au même titre que d'autres valeurs entières, réelles etc.. On manipule donc un objet d'un
type nouveau qui n'est ni un caractère, ni un entier ni un réel mais qui est un objet dont la valeur est
l'adresse d'un autre objet en mémoire centrale. Un tel objet est appelé un pointeur. On imagine tout de
suite certaines opérations de base indispensables, à savoir :
• ayant un objet, on voudrait connaître son adresse ;
• ayant une adresse, on voudrait savoir ce qui est stocké en mémoire à cette adresse.
En C++, toutes ces fonctionnalités existent.
Page 51
1) déclaration d’un pointeur
Pour déclarer un objet de type pointeur, on utilise le symbole "*" et on indique le type des objets dont
le pointeur pourra contenir l'adresse. Par exemple, dans les déclarations suivantes :
Char *pc;
Int *pi;
On pourrait se demander ici pourquoi il est nécessaire d'indiquer le type des objets dont un pointeur
pourra contenir l'adresse. Finalement, il n'y a aucune différence fondamentale entre l'adresse d'un
caractère et celle d'un entier. Dans les deux cas, il s'agit d'un numéro d'octet en mémoire centrale. De
tels numéros peuvent toujours être représentés avec le même format interne quels que soient les objets
auxquels ils renvoient, tout au plus pourront-ils varier en fonction de l'architecture matérielle des
machines (bus d'adresse sur 16, 32 voire 64 bits). En effet, le problème ne se pose pas au niveau de la
représentation interne de la valeur d'un pointeur mais au niveau de l'interprétation du contenu de la
mémoire à l'endroit où il pointe. En d'autres termes, ayant une adresse précise en mémoire, encore faut-
il savoir ce qu'on espère y trouver. Si, par exemple, on s'attend à y trouver un caractère, il ne faudra
prendre en compte que le seul octet se trouvant à cette adresse. Par contre, si on s'attend à y trouver un
entier, il faudra non seulement prendre en compte l'octet se trouvant à cette adresse mais, dans un
environnement ou un entier serait représenté sur 32 bits, également les trois octets suivants, les quatre
formant alors l'entier pointé.
2) initialisation d’un pointeur
pour initialiser un pointeur on utilise l’opérateur d’adresse &. Par exemple
int x;
int *pt;
x = 5;
pt = &x; /* pt contient l’adresse de x */
3) utilisation d’un pointeur
pour faire référence à une variable en utilisant son pointeur, il faut précéder le pointeur par l’opérateur
d’indirection *. Exemple
int x=5, *pt;
pt = &x; /* pt contient l’adresse de x */
cout << *pt << endl; /* elle affiche la valeur 5 */
4) les tableaux et pointeurs
on peut parcourir un tableau en utilisant un pointeur. Exemple
#include < iostream.h >
void main ( )
{
int tab [ 4 ], *pt ;
Page 52
int l;
pt = &tab [0];
for ( l = 0; l<4; l++ )
cin >> *(pt + l);
/** l’affichage du tableau ***/
for ( l = 0; l<4; l++ )
cout << *(pt + l) ;
}
5) le tri d’un tableau avec un pointeur
void main ( )
{
int tab [10], *pt ;
int I ,j;
pt = & tab[0];
for ( I = 0; I<9; I++ )
for ( j = I+1; j<10; j++ )
if ( *(pt + I)] > *(pt + j)
{
temp = *(pt + I);
*(pt + I) = *(pt + j);
*(pt + j) = temp;
}
}
4- Passage de paramètres d’une fonction - Pour rappel, il y a 2 types de paramètres:
o paramètres réels: dans l'appel de fonction
o paramètres formels: dans l'entête de la fonction
- En C++, 3 types de passage de paramètres:
o Par valeur (existe aussi dans les langages C)
o Par adresse (existe aussi dans le langage C)
o Par référence (uniquement dans les langages C++)
Page 53
4-1 Passage de paramètres par valeur
4-2 paramètres par adresses
Page 54
4-3 paramètres par références - En C++ le compilateur peut se charger lui même de la gestion des adresses.
- Le paramètre formel est un alias de l'emplacement mémoire du paramètre réel.
5. Passage d'un tableau
- Deux configurations possibles:
Page 55
5.1. Par pointeur
5.2. Par semi-référence
Page 56
Références
1. Delannoy, « Le langage C++ », Eyrolles Très bon livre pour commencer le C++, livre très
pédagogique. A servi de base pour ces notes de cours.
2. Stroustrup, « Le langage C++ », Addison Wesley, Pearson Education Le livre de référence par
l’auteur du C++. Complet mais beaucoup trop riche pour débuter.
3. Scott Meyers, « Le C++ efficace », Addison Wesley Des règles pour programmer proprement et
efficacement en C++.
4. Schaum, C++ cours et exercices corrigés C++ détaillé avec exemples, exercices corrigés. A servi de
base pour une partie des notes de ce cours. Par contre, les classes, l’héritage et les fonctions virtuelles
ne sont pas assez développés.
5. Johannes Weidl, « The Standard Template Library Tutorial ». Un tutorial sur la STL, accessible sur le
Web. Pour programmeur confirmé.
6. Thinking in C++ Bruce Eckel. Une version française gratuite de cet ouvrage est téléchargeable au lien
suivant :http://bruce eckel.developpez.com/livres/cpp/traduction/ticpp2vol1/
7. Cours Programmation Orientée Objet avec C++, Mohamed Lokbani, accessible au lien
http://www.iro.umontreal.ca/~pift1166
8. Cours Algorithmique et Langage de Programmation C++, Ahmed Bounouar, Collège Ottaouais,
Gatineau, Canada