56
PROGRAMMATION ALGORITHMIQUE LANGAGE C/C++. | Prof. E. El Bachari VERSION 1.0 ALGORITHMIQUE & PROGRAMMATION LANGAGE C/C++.

Poly Copies Mas 3

Embed Size (px)

Citation preview

Page 1: Poly Copies Mas 3

PROGRAMMATION ALGORITHMIQUE LANGAGE C/C++. | Prof. E. El Bachari

VERSION 1.0 ALGORITHMIQUE & PROGRAMMATION

LANGAGE C/C++.

Page 2: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

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: Poly Copies Mas 3

Page 53

4-1 Passage de paramètres par valeur

4-2 paramètres par adresses

Page 54: Poly Copies Mas 3

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: Poly Copies Mas 3

Page 55

5.1. Par pointeur

5.2. Par semi-référence

Page 56: Poly Copies Mas 3

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