Introduction à la Programmation en C ++

Dimension: px
Commencer à balayer dès la page:

Download "Introduction à la Programmation en C ++"

Transcription

1 FACULTÉ POLYTECHNIQUE DE MONS Service d Informatique Introduction à la Programmation en C ++ Mohammed Benjelloun 1 ère Bachelier Année académique

2 FACULTÉ POLYTECHNIQUE DE MONS Service d Informatique Table des matières Avant-propos 1 Chapitre 1 : Introduction Historique Intérêts du langage 2 Chapitre 2 : Eléments du langage Structure d'un programme C Commentaires en C Identificateurs Directives du préprocesseur Points-virgules Type de données Les variables Mots réservés Opérateurs et expressions Opérateurs arithmétiques Conversions de type forcées (casting) Opérateurs logiques et opérateurs de comparaison Opérateurs d'affectation Classes de priorités 14

3 2.10. Nos premiers programmes Le programme C++ le plus court Le premier programme Les entrées/sorties Flux de sortie cout Flux d entrée cin 19 Ce qu il faut au moins retenir 20 Exercices 20 Chapitre 3 : Les structures de contrôle La structure alternative La structure de sélection (switch) Les instructions répétitives Instruction for Instruction while Instruction do... while Instructions de branchement Instruction break Instruction continue Instruction goto 35 Ce qu il faut au moins retenir 35 Exercices 36 Chapitre 4: Les tableaux et les chaînes de caractères Les tableaux Tableaux à une dimension Tableaux à deux dimensions Initialisation et réservation automatique Les chaînes de caractères Déclaration de chaînes de caractères Initialisation de chaînes de caractères Précédence alphabétique et lexicographique 42 Ce qu il faut au moins retenir 46 Exercices 47 Chapitre 5 : Les fonctions Introduction Définition de fonctions Instruction return Appel et déclaration de fonctions Passage de paramètres Passage de paramètres par valeur Tableaux comme paramètres 55

4 5.6. Visibilité des variables Récursivité Surcharge des fonctions Paramètres par défaut 60 Ce qu il faut au moins retenir 61 Exercices 62 Chapitre 6: Les pointeurs et les références Un pointeur: qu'est-ce que c'est? Déclaration de pointeurs Valeurs pointées et adresses Une référence: qu'est-ce que c'est? 66 Déclaration de références Pointeurs, références et arguments de fonctions Pointeurs et tableaux Allocation dynamique de la mémoire 71 Ce qu il faut au moins retenir 73 Exercices 74 Chapitre 7: Les fichiers Généralité Accès aux fichiers Ouverture d un fichier Fermeture d un fichier Lecture et écriture 78 Ce qu il faut au moins retenir 82 Exercices 83 Chapitre 8: Les structures Principes fondamentaux des structures Pointeurs vers les structures Structures et fonctions 87 Ce qu il faut au moins retenir 91 Exercices 92 Chapitre 9: Listes simplement chaînées 98 Chapitre 10: Quelques erreurs à éviter 102 Annexes 106 Annexe A 107 Ordre de priorité des opérateurs 107 Table des codes ASCII des caractères 108 Annexe B : Support des présentations 111

5 Avant-propos Ces notes permettent de se familiariser avec le langage de programmation C++. Elles constituent le support des travaux pratiques et des exercices dans le cadre de l'enseignement du cours d'informatique I de la première année Bachelier à la Faculté Polytechnique de l Umons. Il représente aussi une partie du cours Programmation et Algorithmique dispensé aux étudiants d IG Charleroi. Ce support a pour objectif d'aider l'étudiant dans l'assimilation des principales notions et de certains concepts d'algorithmique vus au cours théorique. Afin d illustrer par la programmation ces concepts, ce syllabus est agrémenté de nombreux exemples et exercices permettant au débutant de mettre immédiatement en application la théorie qu'il vient de lire. Ces notes ne sont donc nullement un manuel de référence du langage C++, mais simplement une aide à l'apprentissage des bases et de la structure du langage. Lors des séances d'exercices, où la présence est obligatoire, un complément de matière sera abordé. Donc le présent document ne peut être considéré comme complet. Notre ambition est d éveiller chez l étudiant le souhait de découvrir ce langage, d utiliser les possibilités offertes par C++ afin de pouvoir écrire ses propres programmes. Certaines constructions syntaxiques sont volontairement omises, par souci de clarté. D'autres concepts, comme l aspect objet (deuxième année bachelier), sont volontairement absents ou ne sont présentés que superficiellement, afin de ne pas accabler le programmeur néophyte. Il ne faut donc pas considérer ce syllabus comme auto-suffisant, mais bien, pour ce qu'il doit être, c'est-à-dire une introduction à la programmation des concepts de base de C++ relative au «plus» par rapport au C, et un support d'exercices et de travaux. Néanmoins, nous espérons qu'il vous permettra de mieux comprendre ce langage et qu'il vous en rendra l'apprentissage plus agréable. Bien entendu, nous ne pouvons que chaudement renvoyer le lecteur désireux d'en savoir plus à l'un des très nombreux ouvrages sur le C++ disponibles dans toutes les bonnes librairies, et notamment à: Bjarne Stroustrup. Le langage C++. Édition revue et corrigée. Pearson Education, La référence de base sur C++, par l'auteur du langage. Complet mais beaucoup trop riche pour débuter. homepage de Bjarne Stroustrup Stanley B. Lippman and Josée Lajoie. C++ Primer. Addison-Wesley, third edition, Très complet (1200 pages), un des meilleurs livres pour apprendre C++. Bruce Eckel. Thinking in C++ Volumes 1 et 2. Téléchargeable gratuitement sur Internet Excellent ouvrage sur C++, Kris Jamsa et Lars Klander. C/C++ La bible du programmeur, 1500 astuces pour toutes les situations. Edition Eyrolles, De nombreux exemples en C et C pages Sur le Web : Cours, tutoriels, livres électroniques et Docs sur C++ : En particulier : le méga-cours de Christian Casteyde (2008) Je voudrais remercier ici les collègues du Service d'informatique qui ont pris soin de relire ces notes et de suggérer corrections et améliorations. Je suis bien conscient qu'il reste des erreurs et/ou des imprécisions. Merci au lecteur assidu de les signaler! Si vous notez la moindre erreur ou si vous souhaitez me proposer vos suggestions, n'hésitez pas à le faire à l adresse suivante : Mohammed.Benjelloun@umons.ac.be

6 Chapitre 1 : Introduction 1.1. Historique Le langage de programmation C++ est un langage parmi d'autres (BASIC, FORTRAN, C, Java,...). Tous ne sont pas équivalents et peuvent avoir des utilisations différentes selon les besoins de l application ou du projet. Il est l'un des langages de programmation les plus utilisés actuellement. Le C++ dont le concepteur est Bjarne Stroustrup (1982), est fortement inspiré de deux autres langages de programmation : Le C : c est un des plus puissants langages évolués. Il trouve ses sources en 1972 dans les 'Bell Laboratories'. Il fut inventé par deux ingénieurs, Dennis Ritchie et Brian Kernighan, pour concevoir un système d'exploitation portable : UNIX. Plus de 90% du noyau UNIX est écrit en C. Ce langage de programmation structuré, d'assez bas niveau, est très proche de la structure matérielle des ordinateurs (mots, adresses, registres, octets, bits,...). C est un langage structuré, modulaire, performant, polyvalent et relativement portable. Il permet de développer des applications à la fois complexes, efficaces et rapides grâce aux structures de contrôle de haut niveau. Le Simula 67 : mis au point en 1967 pour décrire, modéliser (et programmer) et simuler des systèmes complexes comportant des activités parallèles. Il est considéré comme le précurseur de la programmation orienté-objet, basé sur le concept de Class décrivant les attributs et méthodes d'un ensemble d'objets. On peut considérer que le C++ est un langage apparenté au standard ANSI-C à qui on a greffé un système orienté objet. Il reprend d'ailleurs l'ensemble des règles syntaxiques du C, mais il corrige certains points faibles en apportant des améliorations, extensions, nouveautés dont les principales sont liées à la programmation orientée objet inspirée surtout de SIMULA 67 mais aussi de ADA, ALGOL Pour en terminer avec l historique voici quelques dates : 1983 La première version du C++ est utilisée en interne chez ATT 1985 Première implémentation commerciale du C Premiers travaux de normalisation du C Approbation du standard (Ansi C++) par le comité de normalisation 2003 Le standard a été amendé Approbation du standard C Standard en cours Intérêts du langage Nous allons tout au long de ce support étudier le langage C++ qui a su devenir un des langages les plus utilisés en développement. Ce langage est utilisé aussi bien sous UNIX que MacOS ou Windows. Entre autres, la plupart des applications graphiques comportent une partie en C++, ce qui inclut les traitements de textes, utilitaires, jeux,...

7 Chap.1 : Introduction 3 Le langage permet de développer des applications à la fois complexes, efficaces et rapides. Il permet aussi d écrire un code extrêmement concis. Cependant cet atout peut se révéler être un inconvénient car parfois on perd en lisibilité. Les principaux avantages du C++ qui peut être considéré comme un «super C» sont : Structuré : conçu pour traiter les tâches d'un programme en les mettant dans des blocs. Efficace : possédant les mêmes possibilités de contrôle de la machine que l'assembleur, donc générant un code compact et rapide. Il offre aussi un grand nombre de fonctionnalités. Portable : portabilité des fichiers sources. Modulaire : permettant de séparer une application en plusieurs sous-modules s'occupant chacun d'un sous-domaine du problème initial. Objets : facilité d'utilisation du langage objet permettant une meilleure qualité de programmation. Il est à noté que ce syllabus, ne dresse qu une description des concepts de base de C++. En effet, nous n aborderons pas ici l aspect objet (classe, héritage, polymorphisme,...) qui ne rentre pas dans le cadre de l enseignement de cette année mais bien de la deuxième année de bachelier. Ce syllabus est organisé en neuf chapitres, chacun d'entre eux nous permettant de nous focaliser sur chacun des points du langage (les types, les expressions, les instructions, les fonctions, manipulation de pointeurs et références...). Aucune connaissance d'un langage de programmation n'est supposée, mais bien des notions d'algorithmique vue au cours. Les notes, du chapitre 2 au chapitre 8, sont accompagnées de nombreux exemples et programmes d'illustration car un petit exemple valant mieux qu'un long discours!!. Nous appelons un programme un ensemble d instructions contenant tout ce qu il faut afin d être compilé et exécuté. Ces programmes sont représentés comme suit :.. Programme Chap.Num Nous recommandons à nos lecteurs de suivre les styles de programmation suggérés. Ces mêmes chapitres se terminent par une rubrique Ce qu il faut au moins retenir permettant de donner un résumé du chapitre et mettre parfois l accent sur des erreurs ou des pièges dans lesquels tombent souvent les étudiants. Cette rubrique se présente comme suit : Ce qu il faut au moins retenir :..

8 Chap.1 : Introduction 4 Quelques exercices suivent chaque chapitre. Nous invitons le lecteur à les résoudre afin de maîtriser le langage. Les solutions ne se trouvent pas dans ce syllabus : certaines seront proposées en séances de travaux et/ou d exercices ; les étudiants de la faculté désireux d en savoir plus sur les exercices non résolus peuvent me contacter. Le dernier chapitre décrit quelques erreurs observées lors des séances de travaux ou à l examen. La plupart sont des erreurs d'inattention ou proviennent de la syntaxe du langage combinée à l'inattention du programmeur. Le but de ce chapitre est d attirer l attention des étudiants sur ce genre d erreurs afin de les éviter. Enfin, on trouvera en annexes la table de précédence des opérateurs qui fixe l'ordre de priorité ainsi que la table des codes ASCII des caractères. D autres documents comme celui des séances de travaux, le code source des programmes "Programme Chap.Num" d'illustration de ce syllabus, se trouvent sur le site Web

9 Chapitre 2 : Eléments du langage C Structure d'un programme C++ Un programme écrit en C++ doit obéir à certaines règles bien définies. Il est composé des directives du préprocesseur (une ligne de programme commençant par le caractère dièse (#) ) et d une ou plusieurs fonctions stockées dans un ou plusieurs fichiers. Une fonction particulière, dont la présence dans le programme est obligatoire, est la fonction programme principal ou main(). Le programme commencera toujours son exécution au début de cette fonction. Une fonction est un bloc de code d'une ou plusieurs instructions qui peut renvoyer une valeur à la fonction appelante. La forme générale d'une fonction est : Classe [Type] Ident( [liste_de_parametres_formels] ) { Corps_de_la_fonction Les éléments entre [] dans cette syntaxe sont facultatifs, car une valeur par défaut existe. Nous verrons plus tard au chapitre 5 de nombreux exemples de fonctions. La syntaxe précédente appelée déclaration de la fonction contient : Classe : la classe de mémorisation de la fonction qui peut prendre par exemple la valeur static ou extern. Classe peut ne pas exister. Type : le type de la valeur renvoyée par la fonction. Type étant un des types reconnus par le langage C++ comme :void, int, float (voir 2.6). Ident : l identificateur représentant le nom de la fonction (voir 2.3). liste_de_parametres_formels : la liste de paramètres nécessaires pour la bonne exécution de la fonction. Chacun des paramètres ayant un nom et un type. Corps_de_la_fonction : est un corps commençant par une accolade ouvrante { et terminant par une accolade fermante, comportant des déclarations de variables, des instructions devant être exécutées par la fonction. La figure 2.1 nous présente une structure simple d un programme C++. Nous verrons tout au long de ce syllabus, plus en détail et d une manière plus précise, le rôle de chaque bloc. Remarquez cependant les parenthèses obligatoires après les noms des fonctions et les accolades d ouverture et de fermeture délimitant le début et la fin de chaque fonction. La fonction fonc1() retourne une valeur à la fonction appelante main(). Les fonctions fonc2() et main() ne retournent rien. En effet le mot-clé void (vide en anglais) devant ces fonctions, indique qu elles ne retournent aucune valeur. Le (void ) après main indique que cette fonction ne prend aucun argument. Le (int) après fonc1 et fonc2 indique que ces fonctions prennent un argument de type entier. Il faut noter aussi que toutes les instructions doivent se trouver dans main() ou être appelées depuis main() à l aide d une ou de plusieurs fonctions. Tout ce qui est en dehors de main() et qui n est pas appelé dans main() n est pas exécuté. Il ne faut donc pas oublier la fonction main()!

10 Chap. 2 : Eléments du langage C++ 6 #include <iostream> using namespace std; Directives du préprocesseur : accès avant la compilation int fonc1(int x); void fonc2(int y); void main(void) { /* début du bloc de la fonction main*/ int i, j=5, k; // définition des variables locales i = 0 ; j=fonc1(i) ; fonc2(i) ; // fin du bloc de la fonction main int fonc1( int var){.. ;.. ; return var ; void fonc2( int t) { /* Corps de la fonction fonc2 */.. ;.. ; Déclaration des fonctions Programme principal Définitions des fonctions 2.2. Commentaires en C ++ Figure 2.1 : Une structure simple d un programme C++ Dans un programme C++, il est possible (et d ailleurs préférable) d ajouter des commentaires facilitant ainsi la lecture et la compréhension du programme. En effet, comme nous avons la possibilité d'utiliser des expressions compactes, ceci peut parfois rendre le programme moins lisible et sans commentaires ou explications, ces programmes peuvent devenir difficilement compréhensibles. Toute suite de caractères encadrée par les symboles /* et */ correspond à un commentaire, et ne joue évidemment aucun rôle lors de l exécution du programme. Il faut noter aussi le symbole // pour un commentaire sur une seule ligne. Ces commentaires sont donc ignorés par le compilateur et ne sont indispensables que sur le plan de la documentation du programme. Notons que les commentaires imbriqués sont interdits. Exemple 1 syntaxiquement corrects : /* ceci est un commentaire écrit en deux lignes */ // un commentaire sur une seule ligne /* un autre commentaire sur une seule ligne */ syntaxiquement incorrects : /* imbriquer /* ce n est pas autorisé */ donc à éviter */

11 Chap. 2 : Eléments du langage C Identificateurs Un identificateur est un nom donné à un objet du programme (variable, constante, fonction), composé de lettres et de chiffres commençant par une lettre. Le caractère _ (souligné) est considéré comme une lettre. En C/C++, les lettres minuscules sont différenciées des majuscules ainsi TAILLE, Taille et taille sont trois identificateurs différents et peuvent être utilisés dans le même programme. Les mots réservés par le compilateur, dans la syntaxe du C++, ne peuvent être utilisés comme identificateurs à cause des confusions que cela pourrait entraîner. Exemple 2 Identificateurs valides: Xx, y1, fonc1, _position, DEBUT, fin_de_fichier, GSM, FPMs, VeCteuR Identificateurs invalides : 3eme commence par un chiffre x#y caractère non autorisé (#) no-commande caractère non autorisé taux de change caractère non autorisé (espace) main mot réservé (voir 2.8.) 2.4. Directives du préprocesseur Les directives du préprocesseur permettent d'effectuer un prétraitement du programme source avant qu'il soit compilé. On y retrouve ce dont le compilateur a besoin pour compiler correctement un programme. Ces directives sont identifiées par le caractère dièse (# qui constitue un signal au préprocesseur) comme premier caractère de la ligne. On les utilise pour l inclusion de fichiers, compilation conditionnelle, Inclusion de fichiers La directive #include insère, au moment de la compilation, le contenu d'un fichier, généralement réservé à l'inclusion de fichiers appelés fichiers en-tête contenant des déclarations de fonctions précompilées, de définition de types... Il sert à inclure des librairies qui regroupent des ensembles de fonctions qui permettent de faciliter la tâche du programmeur. Ces fichiers sont traditionnellement suffixés par.h (header file), mais en C++, il n'est pas toujours nécessaire de spécifier l'extension.h surtout si on ajoute la déclaration using namespace std; Syntaxe #include <nom-de-fichier> // répertoire standard #include "nom-de-fichier" // répertoire courant : où se trouve le programme Ainsi l instruction suivante : #include <iostream> // Entrées-sorties standard using namespace std; invoque le fichier qui comporte des routines auxiliaires concernant les opérations d entrée/sortie (par exemple saisie au clavier et affichage à l écran).

12 Chap. 2 : Eléments du langage C++ 8 Le C++ fait appel à un ensemble de librairies standards, fournies avec le compilateur, contenant des fonctions prédéfinies permettant de contrôler des aspects tels que le traitement de chaînes de caractères <string>, la manipulation des fonctions mathématiques <math> ou <cmath>, etc. Il faut savoir que la plupart des déclarations de la bibliothèque standard C++ ont été regroupées dans un namespace, appelé std. Ce dernier est un espace de noms auquel appartiennent les routines des flux standard d'entrée/sortie. Ainsi, un programme utilisant des fonctionnalités de la bibliothèque standard comportera idéalement la directive using namespace std; ce qui permettra d inclure des fichiers sans ajouter l extension.h Points-virgules En C++, le point virgule est un terminateur d instruction, on en met donc après chaque instruction. On met également un point virgule après chaque déclaration Type de données Les types de base du C++ sont : les mêmes que les types du C ; le type bool ; la notion de référence ; le type class qui permet de définir les objets. Lors de la programmation, on a besoin de manipuler et de stocker les données. Le langage C++ comme le C est déclaratif et typé. Cela signifie que chaque entité (variables, fonctions, ) manipulée dans un programme doit être déclarée et son type est vérifié à la compilation. Il permet la représentation des données sous différents formats. Les différents types de données de base à partir desquels on peut construire tous les autres types, dits types dérivés (tableaux, structures, unions...) sont les suivants: Type Représentation Signification Intervalle Taille en Exemple octets caractères signed char ou char unsigned char Un caractère unique -128 à à 'a' 'A' 'Z' '\n' '\t' entiers réels signed int ou int unsigned int short ou long float double long double entier signé (par défaut) entier positif spécifie la taille de l'emplacement mémoire utilisé Réel simple précision Réel double précision Réel précision étendue -231 à à à E-37 à +-10 E E-307 à +-10 E ou E La plage de valeur des types peut être représentée comme ceci : char short int int long int float double long double où l'opérateur signifie ici «a une plage de valeur plus petite ou égale que».

13 Chap. 2 : Eléments du langage C++ 9 Le codage en mémoire va déterminer les valeurs limites (minimales, maximales, précision numérique) pour les nombres entiers et réels. On peut définir des types non signés (unsigned) qui correspondent à des valeurs toujours positives. Les caractères sont eux représentés en machine par un entier variant de 128 à 127, correspondant pour les valeurs positives au code ASCII (code standard associant un ensemble de caractères standards à des entiers, voir Annexe A). A noter que les caractères accentués ou spéciaux du français (é, à, ç, ô, ) ne font pas partie du code ASCII. Nous les éviterons donc. Pour obtenir la taille des informations manipulées par C++, on utilisera l opérateur sizeof. Ce dernier retourne la taille en octets d un type ou d une expression passée en paramètre, auquel cas cette expression n est en fait pas évaluée. Par exemple, la taille d un entier i est donnée par sizeof(i). Pour illustration voir Programme 2.4. C++ introduit le type bool (booléen) qui s'accompagne des mots-clés true et false. Là où une condition est attendue on doit mettre une expression de type booléen et il est déconseillé de prendre les entiers pour des booléens et réciproquement. Par exemple le résultat d'une opération logique (&&,, etc.) est de type booléen. Le type bool est bien pratique pour tout ce qui est variables ou fonctions "drapeau". Il existe aussi le type void : il s'agit d'un "pseudo-type" utilisé pour spécifier le fait qu'il n'y a pas de type. Ce type sera surtout utilisé au moment de déclaration des fonctions (fonctions ne renvoyant rien). D autres types comme les structures, les pointeurs ou les références seront détaillés plus loin dans ce syllabus. Par contre le type class ne sera pas abordé dans ce cours Les variables Les variables, qui doivent être déclarées avant leur utilisation, sont des données dont la valeur peut être modifiée durant l'exécution du programme. Chaque variable possède un type de données, une adresse mémoire et un nom qui est son identificateur. Pendant l exécution du programme, elles occupent de la place mémoire. Définir une variable, c est donc associer un type et un identificateur. La syntaxe de cette opération est : Type Ident [= valeur] {, Ident [= valeur]; Dans cette notation, les éléments entre crochets [ ] sont optionnels, les éléments entre accolades { peuvent apparaître 0, 1 ou plusieurs fois. Type est un des types reconnus par le langage C++. Ident est l identificateur représentant le nom par lequel on désigne la variable. valeur est la valeur initiale qu'on souhaite attribuer à la variable. Si, dans la déclaration, la variable n'est pas initialisée (on ne lui attribue pas de valeur initiale), cette dernière peut alors contenir n'importe quoi.

14 Chap. 2 : Eléments du langage C++ 10 Exemple 3 int i, j=5, k; // i, j, k sont des variables de type entier et j est initialisée à 5 float moyenne; // moyenne est une variable de type virgule flottante, char une_lettre; // une_lettre est une variable de type caractère int Compteur = 0; float X = 5.03e-3; Le compilateur réserve la mémoire nécessaire pour stocker ces variables. Leur initialisation n est pas nécessaire lors de la déclaration, mais il est possible de les initialiser par affectation. En utilisant le mot clé réservé const, nous pouvons indiquer que la valeur de cette variable ne change pas (constante) au cours d'un programme comme dans: const int MAX = 1000; const char NEWLINE = '\n'; L initialisation de telles variables est obligatoire lors de leur déclaration. En ce qui concerne le type caractère, il existe des caractères spéciaux (constantes) représentant une séquence d échappement qui seront toujours précédés de l anti-oblique (backslash : \) et sont interprétés comme suit : Caractères Signification CODE ASCII (hexadécimal) \n Génère une nouvelle ligne (newline) 0x0A \t Tabulation horizontale 0x09 \v Tabulation verticale 0x0B \b Retour, supprime le caractère précédent (backspace) 0x08 \r Retour chariot (return) 0x0D \f Saut de page (form feed) 0x0C \a Emet un bip sonore (alarm) 0x07 \\ Affiche une barre oblique inverse (backslash) 0x5C \' Affiche une apostrophe (single quote) 0x2C Remarques : Les variables peuvent être définies quasiment n'importe où dans le programme. Cela permet de ne définir une variable temporaire que là où l'on en a besoin. Cependant, par souci de lisibilité nous préférons (à ce niveau) des déclarations au début des fonctions. La définition d'une variable ne suffit pas, en général, à l'initialiser. Les variables non initialisées contenant des valeurs aléatoires, il faut éviter de les utiliser avant une initialisation correcte. Les variables «constantes» que l'on déclare avec le mot clé const, doivent être initialisées lors de la déclaration Mots réservés L attribution des noms à des identificateurs est soumise à une limitation due au groupe des mots dits réservés ou mots-clés. Les mots réservés du langage sont des noms prédéfinis qui ont une signification particulière, et ne peuvent pas servir de noms de variables personnelles. La signification des mots réservés les plus utilisés sera donnée au fur et à mesure du cours. Nous ne verrons cependant pas ici la signification de tous ces mots réservés.

15 Chap. 2 : Eléments du langage C++ 11 asm auto bool break case catch char class const continue default delete do double else goto if inline int long mutable namespace new operator private protected public register return short signed sizeof static struct switch template this typedef union unsigned using virtual void volatile while 2.9. Opérateurs et expressions Opérateurs arithmétiques Les opérateurs arithmétiques binaires sont : + addition - soustraction * multiplication / division (entière et rationnelle!) % modulo (reste d'une div. entière) 7%2 vaut 1, alors que 7/2 vaut 3. Si l on désire obtenir une division réelle, il faut que le numérateur et/ou le dénominateur soi(en)t réel(s). Ainsi 7.0/2, 7/2.0 et 7.0/2.0 donnent la même valeur, soit 3.5. Le compilateur considère le type des opérandes pour savoir comment effectuer les opérations. Si, par exemple, on a : int i = 6, j = 4, k; double f = 6.0, g = 4.0, h; k = i / j; // k = 6/4 = 1 h = f / g; // h = 6.0/4.0 = 1.5 h = i / j; // h = 6/4 = Les opérateurs + et sont également utilisés comme opérateurs de signes unaires (opérateurs placés devant un entier ou un réel pour indiquer son signe). La priorité dans les évaluations d expression est donnée aux opérateurs unaires + et -, puis aux opérateurs *, / et %, et enfin aux opérateurs binaires + et (voir Annexe A). Par exemple, * -7 = 5 + (3*(-7)) = / = 5 (2/(-1)) + 8 = 15 On peut toujours utiliser des parenthèses en cas de doute de priorité, ce qui peut d ailleurs faciliter la lisibilité. (5 + 3) * (-7) = -56 (5 + 10) / (-1 + 8) = 15/7 = 2 (en arithmétique entière)

16 Chap. 2 : Eléments du langage C++ 12 Les expressions sont formées de combinaisons d opérandes (constantes caractères ou numériques, identificateurs de variables ou de fonctions) et d opérateurs, avec éventuellement des parenthèses. Ainsi, (3*x*x + 5*x*y + 7)/(x + 1) 2*cos(PI*x) exp((0.5)*log(x)) // racine carrée de x où x, y sont des variables réelles, PI une constante réelle, mathématique, sont des expressions correctes. cos(), exp() et log() des fonctions Conversions de type forcées (casting) Il est possible de convertir explicitement une valeur d un certain type vers un autre, quelconque, en forçant la transformation à l'aide de la syntaxe: Exemple 4 (Type) <Expression> Nous divisons deux variables de type entier. Pour avoir plus de précision, nous voulons avoir un résultat de type rationnel. Pour ce faire, nous convertissons l'une des deux opérandes en float. Automatiquement le compilateur convertira l'autre opérande en float et effectuera une division rationnelle: int I=3, J=4; float K; K = (float)i/j; La valeur de I est explicitement convertie en float. La valeur de J est automatiquement convertie en float. Le résultat de la division (type rationnel, valeur 0.75) est affecté à K. Attention! Les contenus de I et de J restent inchangés; seulement les valeurs utilisées dans les calculs sont converties. Exemple 5 float F=65.49, FI; int I=98, IF; char C, CF, CI; IF = (int) F; // IF = 65 CF = (char) F; // CF= A FI = (float) I; // FI= CI = (char)i; // CI= b Opérateurs logiques et opérateurs de comparaison Les opérateurs logiques permettent de calculer des expressions logiques, au résultat vrai, ou faux. Opérateurs logiques && et logique (and) ou logique (or)! négation logique (not) Opérateurs de comparaison == égal à!= différent de <, <=, >, >= plus petit que,...

17 Chap. 2 : Eléments du langage C++ 13 Les résultats de ces opérateurs sont du type booléen. Le résultat d'une expression logique vaut true si elle est vraie et false sinon. Réciproquement, toute valeur non nulle est considérée comme vraie et la valeur nulle comme fausse. Exemple 6 x = = y // vrai si x égal à y (true), faux sinon (false) (val > 0) (val == -10) // vrai si val est positive ou égale à -10 (Car >= 'b') && (Car < 'e') // vrai si le caractère Car vaut 'b', 'c', ou 'd' int i = 7; float f = 5.5; f > 5 ====> true //retourne la valeur true (i + f) <= 1 ====> false Pour les expressions logiques formées de && ou de, le programme évalue tout d abord l expression de gauche, et ensuite celle de droite, mais seulement si le résultat n est pas encore déductible. C'est ce qu'on appelle une évaluation paresseuse.!expr1 est vrai si expr1 est faux et faux si expr1 est vrai ; expr1&&expr2 est vrai si les deux expressions expr1 et expr2 sont vraies et faux sinon. L'expression expr2 n'est évaluée que dans le cas où l'expression expr1 est vraie ; expr1 expr2 = true si expr1= true ou expr2= true et false sinon. L'expression expr2 n'est évaluée que dans le cas où l'expression expr1 est fausse Opérateurs d'affectation Le symbole d affectation = est un opérateur à part entière qui peut être utilisé au sein d expressions. Son rôle consiste à évaluer l expression du membre de droite et à transférer ce résultat comme valeur de l objet au membre de gauche. L instruction d affectation la plus simple est donc : variable = expression ; Une autre instruction tout aussi correcte est variable1 = variable2 = expression ; En pratique, nous retrouvons souvent des affectations comme: i = i + 5 ; /* On prend la valeur contenue dans la variable i, on lui ajoute 5 et on met le résultat dans la variable i. */ En C/C++, il est possible d utiliser une formulation plus compacte: i += 5 ; // réalise la même opération que l instruction précédente L'opérateur += est un opérateur d'affectation. Pour la plupart, les expressions ont la forme: expr1 = (expr1) op (expr2) La formulation équivalente utilisant un opérateur d'affectation est : expr1 op= expr2 Opérateurs d'affectation += ajouter à -= diminuer de *= multiplier par /= diviser par %= modulo Ainsi ces expressions sont équivalentes : X= X + 32 ; X += 32 ; F= F/1.5 ; F /= 1.5 ; I= I *(J+10); I *= J+10; Tab[n*i+j]= Tab[n*i+j]*3; Tab[n*i+j] *= 3;

18 Chap. 2 : Eléments du langage C++ 14 Le C/C++ fournit aussi d autres opérateurs contractés pour des opérations usuelles. Ainsi l'opérateur d'incrémentation ++ ajoute 1 à son opérande entière. De même l'opérateur de décrémentation -- retranche 1 à son opérande. On peut les utiliser soit devant une variable (préfixé : mise à jour de la variable avant son utilisation dans l'expression courante), soit derrière la variable (postfixé : mise à jour après son utilisation dans l'expression courante). Exemple 7 int i=4, j=3, k; i++; // équivalent à i= i+1, donc i vaut maintenant 5 --j; // équivalent à j= j-1, donc j vaut maintenant 2 k = ++i; // i = i+1 puis k = i, donc i=k= 6 k = j--; // k = j puis j=j-1, donc k vaut 2 et j vaut 1 Ce dernier exemple nous incite à faire attention lors de l utilisation des opérateurs contractés. Il faut savoir quand utiliser une variable préfixée ou postfixée. La confusion entre les deux peut induire des erreurs dans le programme. Il est à noter que les formulations compactes ne sont pas obligatoires et n ont pour rôle que de réduire la quantité de code du programme. Voici une explication sur l utilisation de la forme compacte pour incrémenter/décrémenter une variable et en même temps affecter sa valeur à une autre variable : postfixe préfixe X = I++ X = I-- X = ++I X = --I passe d'abord la valeur de I à X et incrémente I après passe d'abord la valeur de I à X et décrémente I après incrémente d'abord I et passe la valeur incrémentée à X décrémente d'abord I et passe la valeur décrémentée à X Classes de priorités Parmi les opérateurs que nous connaissons jusqu'ici, nous pouvons distinguer les classes de priorités suivantes: Priorité 1 (la plus forte): ( ) Priorité 2:! Priorité 3: * / % Priorité 4: + - Priorité 5: < <= > >= Priorité 6: ==!= Priorité 7: Priorité 8: && Priorité 9 (la plus faible): = += -= *= /= %= Evaluation d'opérateurs de la même classe : Dans chaque classe de priorité, les opérateurs ont la même priorité. Si nous avons une suite d'opérateurs binaires de la même classe, l'évaluation se fait en passant de la gauche vers la droite dans l'expression. Pour les opérateurs unaires (!,++,--) et pour les opérateurs d'affectation (=,+=,-=,*=,/=,%=), l'évaluation se fait de droite à gauche dans l'expression.

19 Chap. 2 : Eléments du langage C Nos premiers programmes Un fichier source C++ correspond à un fichier texte contenant des lignes de code. Ce fichier prend généralement pour extension.cpp. Lorsqu'un programme est chargé, son exécution commence par l'appel d'une fonction spéciale du programme. Cette fonction doit impérativement s'appeler main() (principal en anglais) pour que le compilateur puisse savoir que c'est cette fonction qui marque le début du programme Le programme C++ le plus court Notre premier programme est le programme C++ le plus court à écrire. Et pour cause, c est un programme qui ne fait rien. Il est constitué uniquement de la fonction main(), obligatoire pour que le programme soit exécutable. void main (void) { Cette fonction ne retourne aucune valeur (premier void) et ne prend aucun argument (deuxième void). Les parenthèses après main sont obligatoires, elles spécifient que l on est en train de décrire une fonction. Les accolades { encadrent un bloc d'instructions (ensemble de déclarations et instructions exécutables), constituant le Corps_de_la_fonction. Dans notre exemple, ce corps est vide, donc le programme ne fera rien Le premier programme A titre d exemple, notre premier programme devient le programme 2.1 qui calcule la circonférence et la surface d un disque. void main(void) /* Ce programme calcule la circonférence et la surface d un disque de rayon 2 */ { const float PI = ; // initialisation de la constante PI int rayon = 2; // initialisation de la variable rayon float circonference, surface, temp; // déclaration des variables réelles temp = PI*rayon; circonference = 2*temp; surface = temp*rayon ; // affectation d une variable temporaire // calcul de la circonférence // calcul de la surface Programme 2.1 L exécution de ce programme n affichera aucun résultat à l utilisateur. En effet, aucune fonction d affichage n a été invoquée! Les entrées/sorties En C++, la saisie/affichage ou entrée/sortie (I/O) est gérée par des librairies, c est-à-dire des ensembles de fonctions/objets standard pré-programmées, livrées avec les compilateurs. Un programme qui utilise les flux standard d'entrée/sortie doit comporter la directive #include <iostream.h> ou #include <iostream> + using namespace std

20 Chap. 2 : Eléments du langage C++ 16 Les flux d'entrée/sortie sont représentés dans les programmes par les trois variables (objet flot, stream), pré-déclarées et pré-initialisées, suivantes : cout, le flux standard de sortie, habituellement associé à l'écran, cin, le flux standard d entrée, habituellement associé au clavier, cerr, le flux standard pour la sortie des messages d erreur associé à l écran. Les écritures et lectures se font à l'aide des opérateurs <<, appelé opérateur d'injection (injection de données dans un flux de sortie), et >>, appelé opérateur d'extraction (extraction de données d'un flux d'entrée). Le namespace, appelé std est un espace de noms auquel appartient cout et cin. La directive using namespace std; permettra d inclure des fichiers sans ajouter l extension.h et évitera d'avoir à écrire explicitement std::cout,par exemple Flux de sortie cout Le flux de sortie cout permet d afficher tous les types de valeurs à l écran. Syntaxe : cout << expression << expression << expression ; Description : Permet l'écriture (à l'écran par défaut). Pour utiliser cout dans un programme, il faut inclure la librairie standard I/O <iostream>. #include <iostream.> using namespace std ; // pour standard I/O // utilisation de l espace de nommage std void main(void){ int i=5, j= 10 ; // déclaration et initialisation de deux entiers i et j cout << i << " " << i+1 << endl; // Affiche la valeur de i et de i+1 cout << i << " " << j << endl; // Affiche la valeur de i et de j cout << " =" << << endl; // Affiche : = 120 cout << "Salut a tous " << endl; // Affiche le texte entre " " Programme 2.2 Remarquez que nous évitons d'utiliser des caractères spéciaux (à,é,à,è,ù,ô, ) dans les affichages. Leur traitement dépend en effet des compilateurs et sort du cadre de la norme ANSI. endl signifie le saut de ligne, il représente la même chose que \n. Ainsi, les deux écritures sont équivalentes Et si l on désire afficher les résultats du programme 2.1

21 Chap. 2 : Eléments du langage C++ 17 #include <iostream> // pour standard I/O ; using namespace std; // utilisation de l espace de nommage std void main(void) // Ce programme calcule et affiche la circonférence et la surface d'un disque de rayon 2 { const float PI = ; // initialisation de la constante PI int rayon = 2; // initialisation de la variable rayon float circonference, surface, temp; // déclaration des variables réelles temp = PI*rayon; // affectation d'une variable temporaire circonference = 2*temp; // calcul de la circonférence surface = temp*rayon ; // calcul de la surface cout << "La surface d'un disque de rayon " << rayon << " vaut " << surface << endl; // (1) cout << "La circonference vaut " << circonference << endl; Programme 2.3 cout permet de placer des valeurs de types différents dans la même instruction comme le montre (1). Voici ce qu affiche l exécution du programme 2.3 : La surface d'un disque de rayon 2 vaut La circonference vaut Maintenant que nous savons comment afficher des informations à l écran, voici un exemple qui permet d obtenir la taille des informations manipulées par C++ à l aide de l opérateur sizeof vu auparavant. Solution : char= 1 unsigned char = 1 int = 4 unsigned int = 4 short = 2 unsigned short = 2 long = 4 unsigned long = 4 float = 4 double = 8 long double = 8 Programme 2.4 Extension de l utilisation de cout #include <iostream> using namespace std; void main(void) { char c; unsigned char cu; int i; unsigned int iu; short int is; unsigned short int isu; long int il; unsigned long int ilu; float f; double d; long double ld; cout << "\n char= " << sizeof(c) << "\n unsigned char = " << sizeof(cu) << "\n int = " << sizeof(i) << "\n unsigned int = " << sizeof(iu) << "\n short = " << sizeof(is) << "\n unsigned short = " << sizeof(isu) << "\n long = " << sizeof(il) << "\n unsigned long = " << sizeof(ilu) << "\n float = " << sizeof(f) << "\n double = " << sizeof(d) << "\n long double = " << sizeof(ld) << endl; Le flux de sortie cout offre plusieurs possibilités (fonctions membres) pour améliorer l affichage de données. Parmi celles-ci nous trouvons : a) Précision : Si l on désire spécifier la précision d une valeur lors de l affichage, voici un exemple qui illustre le fonctionnement :

22 Chap. 2 : Eléments du langage C++ 18 #include <iostream> // pour standard I/O using namespace std; // utilisation de l espace de nommage std pour importer les symboles de la bibliothèque standard C++ void main(void) { const double V= ; cout << "V vaut : " << V << endl; cout.precision(2); /*manipulateur (fonction membre) de cout : tous les flottants QUI SUIVENT seront affichés avec une précision de 2 chiffres */ cout << "avec precision de 2 -- V vaut : " << V << endl; cout.precision(4); cout << "avec precision de 4 -- V vaut : " << V << endl; cout.precision(6); cout << "avec precision de 6 -- V vaut : " << V << endl; cout.precision(8); cout << "avec precision de 8 -- V vaut : " << V << endl; Programme 2.5 et dont le résultat à l affichage est le suivant : V vaut : avec precision de 2 -- V vaut : 5.1 avec precision de 4 -- V vaut : avec precision de 6 -- V vaut : avec precision de 8 -- V vaut : b) Largeur des champs : La fonction width indique le nombre minimal de caractères du champ de sortie. #include <iostream> using namespace std; void main(void) { int i = 0; cout.width(5); cout << i << '\n'; i = 1; cout.width(5); cout << i << '\n'; Solutions : Flux d entrée cin #include <iostream> using namespace std; void main(void) { int i = 0; cout.width(i+3); cout << i << '\n'; i = 1; cout.width(i+3); cout << i << '\n'; 0 1 Programme 2.6 #include <iostream> using namespace std; void main(void) { int i = 0; cout.fill('.'); // voir résultats cout.width(i+3); cout << i << '\n'; i = 1; cout.fill('.'); // voir résultats cout.width(i+3); cout << i << '\n'; Si pour l affichage on utilise le flux de sortie cout qui repose sur l opérateur <<, pour la saisie on utilise son dual, le flux d entrée cin qui repose sur l opérateur >>. cin est aussi définie dans la librairie <iostream>. Syntaxe : cin >> valeur >> valeur >> valeur ; Description : Permet la saisie (du clavier en principe).

23 Chap. 2 : Eléments du langage C++ 19 #include <iostream> using namespace std; void main () { int n=2; float x= 3.4; char C= 'A' ; cout << " Entier n = "<< n << " ; Entrez un nouveau = " ; cin >> n ; cout << " Float x = "<< x << " ; Entrez un nouveau = " ; cin >> x ; cout << " Char C = "<< C << " ; Entrez un nouveau = " ; cin >> C ; cout << "\n L'entier vaut maintenant : " << n << endl; cout << " Le flottant vaut maintenant :" << x << endl; cout << " Le caractere vaut maintenant :" << C << endl ; L exécution nous donne : Entier n = 2 ; Entrez un nouveau = 3 Float x = 3.4 ; Entrez un nouveau = 5.67 Char C = A ; Entrez un nouveau = y L'entier vaut maintenant : 3 Le flottant vaut maintenant :5.67 Le caractere vaut maintenant :y Nous pouvons aussi améliorer notre programme 2.3. Le rayon peut alors prendre n importe quelle valeur réelle puisque sa valeur est demandée à l utilisateur. #include <iostream> using namespace std; void main(void) { const float PI = ; float circonference, surface, temp, rayon; cout << "Quel est la valeur de ton Rayon : " ; cin >> rayon; // initialisation de la constante PI // déclaration des variables réelles temp = PI*rayon; // affectation d'une variable temporaire circonference = 2*temp; // calcul de la circonférence surface = temp*rayon ; // calcul de la surface cout << "La surface d'un disque de rayon " << rayon << " vaut " << surface << endl; cout << "La circonference vaut " << circonference << endl; Programme 2.8 La solution du programme 2.8 est : Quel est la valeur de ton Rayon : 5 La surface d'un disque de rayon 5 vaut La circonference vaut

24 Chap. 2 : Eléments du langage C++ 20 Ce qu il faut au moins retenir : Avant d utiliser cin pour la saisie et cout pour l affichage, il faut d abord inclure la librairie standard I/O : OU #include <iostream.h> #include <iostream> using namespace std; cout << "Quel est la valeur de ton Rayon : " ; cin >> rayon; Une constante est une donnée dont la valeur ne peut pas être modifiée durant toute sa durée de vie. Il est indispensable d'initialiser la constante au moment de sa définition avec le mot réservé const : const int DEBUT = 10 ; // ou const DEBUT = 10 ; Avant de manipuler une variable I (I++, I--, etc.) ou de l afficher, il faut la déclarer et l initialiser. Exercices 2.1. Citer parmi les identificateurs suivants ceux qui sont valides et ceux qui ne le sont pas. a) record b)long c) %interet d) étudiant e) MaVariable3 f) ma_var_4 g) 2x h) Long i) double j) ma-var Les déclarations suivantes sont-elles correctes? Les corriger si nécessaire. a) int i = 3, j, k = 5; b) float x = y = z = 1.0; c) char c = "bonjour"; d) char d = '\n'; 2.3. Les appels suivants d'affichage vont-ils correctement s'exécuter? A défaut, comment les corriger? int i = 7, j = 8; char c = 'a'; float x = 3.5; cout << i=, j=,c << (i,j,c) ; cout << " i=, j=,c "<< (i,j,c) ; cout >> " i= " >> i ; cout << " i= " << i ; cin << " i= " << i ; cout >> " i= " >> x ; 2.4. Corriger le programme suivant pour qu il s exécute correctement. Main() float k; { int i, j=k ; cout << " i= " << i << "alors entrer la valeur de j " << j ; cin << " j= " << j ;

25 Chapitre 3 : Les structures de contrôle Les structures de contrôle définissent la suite dans laquelle les instructions sont effectuées et la façon de contrôler le déroulement du programme. Dans ce chapitre, nous allons voir ce que met à notre disposition le langage C++ comme structures dites de contrôle de flux. Constatons déjà que la particularité la plus importante des instructions de contrôle en C++ est le fait que les 'conditions ' peuvent être des expressions quelconques qui fournissent une valeur logique vraie (true) ou fausse (false) La structure alternative La structure alternative (ou instruction conditionnelle) permet de ne pas exécuter systématiquement certaines instructions, mais seulement dans certains cas bien prévus par le programmeur. En langage algorithmique une structure alternative peut s écrire de la manière suivante : si (<expression logique>) alors <bloc d'instructions 1> sinon <bloc d'instructions 2> fsi // Si l'<expression logique> a la valeur logique vrai, // alors // ce bloc est exécuté // Si l'<expression logique> a la valeur logique faux, // ce bloc est exécuté // fin de si Son organigramme se présente comme suit : oui Condition vraie non oui Condition vraie non n Bloc d instructions 1 Bloc d instructions 2 Bloc d instructions Suite du programme Suite du programme La partie sinon est facultative. On peut donc utiliser si sans la partie sinon. Cette structure alternative se programme en C++ comme suit (if-else): if ( <expression logique > ) <bloc d'instructions 1> else <bloc d'instructions 2> if ( <expression logique > ) <bloc d'instructions >

26 Chap. 3 : Les structures de contrôle 22 La partie <expression logique > peut désigner : une variable d'un type numérique, une expression retournant un résultat numérique. La partie <bloc d'instructions> peut désigner : un bloc d'instructions compris entre accolades, une seule instruction terminée par un point-virgule. Si <expression logique > est vrai <bloc d'instructions 1> est exécuté. Dans le cas contraire c est <bloc d'instructions 2> qui est exécuté. Exemple 1 if (i < 10) i++; //La variable i ne sera incrémentée que si elle a une valeur inférieure à 10. Exemple 2 if (a > b) max = a; else max = b; Le langage possède un opérateur ternaire qui peut être utilisé comme alternative à if-else et qui a l'avantage de pouvoir être intégré dans une expression: <expr1>? <expr2> : <expr3> L exemple 2, en utilisant l opérateur ternaire peut être écrit comme: max = (a > b)? a : b; // max contiendra a si a est plus grand que b, et b sinon Exemple 3 if (A-B) else cout << "A est different de B " << "\n"; cout << " A est egal a B " << endl; Exemple 4 if ( (!j) && (i < 10) && (n!=0) ){ i++; moy = som/n; cout << " la valeur de i = " << i << " et moy= " <<moy ; else { cout << "erreur "; i = i +2 ; Exemple 5 if ( (i%2) ==1 ) { /* Attention de ne pas confondre == (opérateur logique d'égalité) et = (opérateur d'affectation) */ cout <<"Introduisez un entier j = "; cin >> j ; cout <<"division par 2 = " << j/2.0 << endl; else { cout << "Introduisez un caractere C : " ; cin >> k ; cout << " i = " << i << endl << " C = " << k << endl;

27 Chap. 3 : Les structures de contrôle 23 Remarque importante : Rappelez-vous que, x = 0 est une expression valide en C++ qui affecte à x la valeur zéro et qui retourne la valeur affectée, c'est-à-dire zéro. Il est donc parfaitement légal d'écrire : if (x = 0) { // /* traitement */... Malheureusement, if(x=0) a pour effet : quelque soit la valeur de x, elle deviendra zéro. Il faut donc écrire : if (x = = 0) { /* traitement */... Parfois, on a besoin de traiter des décisions emboîtées: si ceci est vrai, faire cela; sinon, si ceci est vrai, faire cela, On imbrique alors plusieurs instructions if-else l'une dans l'autre. En combinant plusieurs structures if-else en une expression nous obtenons une structure qui est très courante pour prendre des décisions entre plusieurs alternatives: Les structures de décision imbriquées s'écrivent par la construction abrégée: if ( <expr1> ) <bloc1> else if (<expr2>) <bloc2> else if (<expr3>) <bloc3> else if (<exprn>) <blocn> else <blocn+1> Les expressions <expr1>... <exprn> sont évaluées du haut vers le bas jusqu'à ce que l'une d'elles soit différente de zéro. Le bloc d'instructions lié à cette dernière est alors exécuté et le traitement de la commande est terminé. Remarque : Comme dans tout langage de programmation, il y a lieu d'être très soigneux dans l'indentation (structuration et alignement des instructions et des blocs). Dans le cas des structures if-else cela permet de bien cerner à quelle instruction if chaque else se rattache. En C++, par convention, une partie else est toujours liée au dernier if qui ne possède pas de partie else. Pour éviter des confusions et pour forcer une certaine interprétation d'une expression, il est recommandé d'utiliser des accolades {.

28 Chap. 3 : Les structures de contrôle 24 Exemple 6 #include <iostream> using namespace std; void main() { char C; cout << "Continuer (O)ui / (N)on?" ; cin >> C ; if (C=='O'){ cout << " OKKK " << endl; else if (C=='N'){ cout << "Au revoir..."; else{ cout << "\a " << " Il faut choisir entre O et N!" << endl; 3.2. La structure de sélection (switch) L'instruction switch est une sorte d'aiguillage, elle est commode pour les "menus". Elle permet de remplacer plusieurs instructions if-else imbriquées. Cette instruction permet de gagner en lisibilité quand le nombre de if-else imbriqués augmente. La variable de contrôle est comparée à la valeur des constantes de chaque cas (case). Si la comparaison réussit, les instructions du case sont exécutées jusqu'à la première instruction break rencontrée. switch (variable_controle) // au cas où la variable vaut: { case valeur1 : ensemble_instruction1; // cette valeur1(étiquette): exécuter ce bloc d'instructions. break; // sortie du case case valeur2 : ensemble_instruction2; break; case valeur3 : ensemble_instruction3; break;.... default : ensemble_instructionn; /* cas par défaut si aucune des valeurs précédentes: exécuter ce bloc d'instructions. Facultatif mais recommandé */ variable_controle doit être de type int, short, char ou long. break fait sortir du sélecteur. En l'absence de break, l'instruction suivante est exécutée; on peut ainsi tester plusieurs cas différents et leur attribuer la même instruction. Le bloc "default" n'est pas obligatoire. valeur1, valeur2,. doivent être des expressions constantes. L instruction switch correspond à une cascade d instructions if...else.

29 Chap. 3 : Les structures de contrôle 25 Exemple 7 char choix; cout<<"tapez un entier entre 1 et 3 :"; cin>> choix; switch(choix) { case '1' : cout<<"vous avez tape 1 "<<endl; break; case '2' : cout<<"vous avez tape 2 "<<endl; break; case '3' : cout<<"vous avez tape 3"<<endl; break; default: cout << "Mauvais choix, Tapez 1 ou 2 ou 3 \n"; Notez la présence d un : (deux points) après la valeur des étiquettes case. l étiquette case '1': intercepte le cas où choix est égal à la valeur '1', le bloc d instruction simple : cout << "ensemble_instruction1 : case 1" << endl; est alors exécuté, puis l instruction break nous fait sortir du bloc switch. Cette instruction break (voir ) est indispensable, sans elle l exécution continuerait linéairement avec le bloc 2 : cout << "ensemble_instruction2 : case 2" << endl; l étiquette case '2': atteinte si choix est égal à '2'. l étiquette case '3': atteinte si choix est égal à '3'. l étiquette default : atteinte si choix est différent de '1', '2' ou '3'. Dans le cas où la variable choix est un entier, l exemple 7 devient: Remarques : int choix; cout<<"tapez un entier entre 1 et 3 :"; cin>> choix; switch(choix) { case 1: cout<<"vous avez tape 1 "<<endl; break; case 2: cout<<"vous avez tape 2 "<<endl; break; case 3: cout<<"vous avez tape 3"<<endl; break; default: cout << "Mauvais choix, Tapez 1 ou 2 ou 3 \n"; Une étiquette ne peut pas définir un intervalle de valeur. Par exemple case 1..5: ou case 1&&5: sont interdits; on écrira à la place plusieurs case. Les valeurs des étiquettes n exigent ni d être ordonnées ni de former une série discrète (1, 2, 3 ). La valeur d une étiquette doit pouvoir être évaluée au moment de la compilation et être soit une valeur entière soit un caractère. Ainsi case 5*j ou case 6.0 ne sont pas correctes. L étiquette default est optionnelle mais recommandée. Le break dans l étiquette default n est pas nécessaire car cette branche est la dernière des étiquettes case concernée par les instructions.

30 Chap. 3 : Les structures de contrôle Les instructions répétitives En C++, nous disposons de trois structures de contrôle d'itérations, appelées aussi structures répétitives ou encore boucles, qui nous permettent d exécuter plusieurs fois certaines phases de programmes. Les boucles conditionnelles sont: 1) la structure : for (pour ) 2) la structure : while (tant que...), 3) la structure : do - while (faire tant que) Ces boucles ont toutes en commun le fait que l exécution des instructions à répéter dépend, comme avec les instructions alternatives, d une condition (<expression logique >) Instruction for La syntaxe de l instruction for est : for (initialisation ; <expression logique > ; itération) { liste d'instructions avec liste d'instructions qui est une instruction simple ou composée. Exemple 8 int compt ; for (compt = 0 ; compt<=5; compt++) { cout << compt << " " ; résultat de l'exécution Cette boucle définit un compteur de nom compt, qui évolue de 0 à 5 en s incrémentant à chaque passage. Ce programme pourrait se traduire par Initialiser un compteur compt à 0. Tant que le compteur est inférieur ou égal à 5, afficher la valeur de compt, incrémenter le compteur de 1. Le compteur, une variable entière, prend successivement les valeurs 0, 1,.., 5. for (compt = 0 ;..) { Correspond à la première instruction "initialisation" qui sert à initialiser les variables. Il est recommandé que ces variables de contrôle de l instruction for soient des variables locales. C est pour cette raison que l on peut déclarer une variable de boucle directement dans l'instruction for. Ceci permet de n'utiliser cette variable que dans le bloc de la boucle. for (int compt = 0 ; compt<=5; compt++){ L expression logique ou test "compt<=5 ", est la condition d'arrêt de la boucle. Elle est évaluée avant d'entrer dans la boucle. Si le test est vrai (true), le bloc est exécuté et donc la boucle se poursuit. Si par exemple le test était le suivant : for (compt = 0 ; compt<0;..) {

31 Chap. 3 : Les structures de contrôle 27 le corps de la boucle ne serait jamais exécuté car compt (initialisé à zéro) ne vérifie pas la condition test (zéro n est pas strictement inférieur à zéro). La condition " itération " " compt++" est l'opération à effectuer en fin de boucle sur la variable de contrôle compt. Dans ce cas-ci, c est une incrémentation. Les trois expressions "initialisation", "<expression logique > " et " itération " peuvent comporter plusieurs instructions pouvant être de types différents. Il suffit pour cela de séparer les différentes instructions par des virgules. Dans le programme suivant : #include <iostream> using namespace std; void main() { int i,j, k=9; float F, r; for ( i=0, j=5, r=0.0; (i<j) && (k!=0) ; i++, j++, k--, r+= 0.2) { F=(float)i/k ; F= F + r; cout << " i= " << i <<" j= " << j << " k= " << k << " F= " << F << endl; Programme 3.1 l expression initialisation contient trois initialisations : i=0, j=5 et r=0.0. Remarquons que ces variables sont de types différents. L expression <expression logique > combine deux vérifications i inférieur à j et k différent de zéro grâce à l opérateur et logique noté &&. L expression " itération " modifie quatre variables : i, j, k et r. #include <iostream> using namespace std; void main() { int I, nombre=1, pairs, impairs, Val_Max; pairs = 0; impairs = 0; cout << "Val_Max? = "; cin >> Val_Max ; // Saisie de Val_Max nombres maximum avec décompte des nombres pairs et impairs for (I = 0; I < Val_Max && nombre!= 0; I++, ((nombre % 2) == 0)? pairs++ : impairs++ ) { cout << "\ntapez votre " << I+1 << ( (I== 0)? "er" : "eme" ) << " nombre (0 pour sortir): "; cin >> nombre; cout << "Votre nombre est " << nombre << endl; cout << "\n\nvous avez tape " << pairs << " nombre(s) pair(s)"; cout << " et " << impairs << " nombre(s) impair(s)\n"; Programme 3.2

32 Chap. 3 : Les structures de contrôle 28 Dans ce dernier programme, le contenu de la boucle est répété tant que le compteur I est inférieur à Val_Max et que l utilisateur ne rentre pas la valeur zéro. Cet exemple montre que l on peut éventuellement utiliser des tests dans l expression "itération ". En effet, on incrémente compteur ("I++") et, selon le résultat du test nombre % 2 qui retourne 0 si nombre est pair et 1 s il est impair, on incrémente pairs ou impairs. Les trois expressions "initialisation", "<expression logique > " et " itération " sont facultatives, ainsi le bloc : for ( ; ; ) { est un bloc d instruction valide, vide et répété à l infini comme le montre le programme suivant : #include <iostream> using namespace std; void main() { char c ; for ( ; ; ){ // Saisie et affichage d'un caractère tant qu'il est différent de S cout << "\ntapez votre caractere (S pour sortir): " ; cin >> c; if (c =='S') break; else cout << "Votre caractere est "<< c ; cout << "\n\n Fin du programme \n" ; Programme 3.3 L exécution de ce programme peut présenter des problèmes liés à l acquisition des caractères. Elle peut se passer de la manière suivante : Tapez votre caractere (S pour sortir): q Votre caractere est q Tapez votre caractere (S pour sortir): s Votre caractere est s Tapez votre caractere (S pour sortir): S Fin du programme

33 Chap. 3 : Les structures de contrôle Instruction while Il s'agit de l'instruction: tant que (<expression logique >) // Condition vraie faire{ BLOC D'INSTRUCTIONS Organigramme: oui Bloc d instruction s Condition vraie non Suite du programme La syntaxe de l instruction while est : while (<expression logique > ) instruction ; L instruction de boucle while permet de réaliser un traitement tant qu une <expression logique > est vraie. Remarques : L'expression <expression logique > est toujours placée entre parenthèses et les { ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction. On peut rencontrer la construction suivante: while (<expression logique >); terminée par un ; et sans la présence du bloc d'instructions. Cette construction signifie: "tant que l'expression est vraie, attendre". Comme toujours, si le bloc instruction est composé de plusieurs instructions, on les placera entre les symboles de début et de fin de bloc: { et soit : while (<expression logique > ) { instruction 1; instruction 2;... Le test se fait d'abord, le bloc d'instructions n'est exécuté que si <expression logique > est vraie. A chaque exécution du bloc, la condition est réévaluée, et ainsi de suite. Dès que l'expression est fausse, on sort de la boucle. Ainsi dans l exemple suivant, le corps de la boucle sera exécuté 3 fois (valeurs i=3,4,5). A la sortie de la boucle, i vaudra 6. int i=3; while ( i < 6 ) { i++;

34 Chap. 3 : Les structures de contrôle 30 Il est fréquent de voir une partie du travail ou la totalité reportée dans l'expression comme le montre ces codes : char C; cout << "Donner un ou plusieurs caractere(s) : "; for ( ; ; ) { cin >> C; if(c=='&') break; else cout << C ; for ( ; ; ) if ((C = cin.get()) == '&') break; else cout << C ; // ou cout.put(c) while ((C = cin.get())!= '&') cout.put(c); cin.get() : permet de saisir un caractère et cout.put(c) permet d afficher le caractère C. Exemple 9 L exemple 8 devient en utilisant la boucle while : int compt=0 ; while (compt<=5 ) { cout << compt << " " ; compt++; Cette boucle est équivalente aussi à : int compt=0; for ( ; compt<=5; ) { cout << compt << " " ; compt++; En fait, la boucle while est une boucle for avec une initialisation avant la boucle et l incrémentation à l intérieur du bloc d instructions. Voici un exemple qui illustre le fonctionnement de la boucle while : #include <iostream> using namespace std; void main() { bool sortir = false; char rep; cout<<"avant la boucle"<<endl; // le booléen pour le cas d'arrêt de la boucle // un caractère pour stocker la réponse while(!sortir) //!sortir équivaut à si sortir == false { // TantQue (sortir est false = FAUX) exécuter le corps de la boucle. cout<<"dans la boucle"<<endl; cout<<"voulez vous quitter (O/N)?"<<endl; cin>>rep; if(rep=='o') sortir=true; cout<<"apres la boucle"<<endl; // Si sortir deviens true (VRAI) alors on sort de la boucle sans exécuter le corps. Programme 3.4

35 Chap. 3 : Les structures de contrôle 31 Le programme 3.2 devient en utilisant la boucle while : #include <iostream> using namespace std; void main() { int I, nombre=1, pairs, impairs, Val_Max; pairs = impairs = I =0; cout << "Val_Max? = "; cin >> Val_Max ; while (I < Val_Max && nombre!= 0) { cout << "\ntapez votre " << I+1 << ( (I== 0)? "er" : "eme" ) << " nombre (0 pour sortir): "; cin >> nombre; cout << "Votre nombre est " << nombre << endl; I++ ; ((nombre % 2) == 0)? pairs++ : impairs++ ; cout << "\n\nvous avez tape " << pairs << " nombre(s) pair(s)"; cout << " et " << impairs << " nombre(s) impair(s)\n"; Programme 3.5 Programme 3.6 : Saisir une suite de caractères, compter et afficher le nombre total de caractères, de lettres a et b. #include <iostream> using namespace std; void main(){ char c; int compt_a= 0,compt_b= 0, compt_tot= 0; cout << "ENTREZ UNE PHRASE: "; while((c=cin.get())!='\n') { if(c=='a') compt_a++; if(c=='b') compt_b++; compt_tot++ ; // l'utilisateur saisit la totalité de sa phrase /*lors du 1er passage, cin.get() ne prend en compte que le 1er caractère, les autres sont rangés dans le tampon */ // et récupérés par cin.get() lors des autres passages cout <<"NOMBRE DE a: "<< compt_a << " de b : " << compt_b << " total : " << compt_tot; Programme 3.6 Voici un exemple d exécution : ENTREZ UNE PHRASE: abracadabra magie NOMBRE DE a: 6, de b :2 et le total = 17

36 Chap. 3 : Les structures de contrôle 32 #include <iostream> using namespace std; void main() { const int NMAX = 20; int NE; cout << "Entrez une valeur entiere positive inferieure ou egale a " << NMAX << " = "; cin >> NE; while((ne<=0) (NE>NMAX)) { if (NE<=0) cout << "j'ai demande une valeur positive, redonnez la valeur : " ; else cout << "j'ai demande une valeur inferieure a " << NMAX << " redonnez la valeur : "; cin >> NE; cout << "La valeur de NE= " << NE << " est OK "; Instruction do... while Programme 3.7 : un exemple qui interdit d introduire des valeurs extérieures à un intervalle prédéfini. Il s'agit de l'instruction: faire{ BLOC D'INSTRUCTIONS tant que (<expression logique >) ; // Condition vraie Il est parfois utile de faire le test non pas avant l'entrée de la boucle, mais à la sortie de celle-ci. Dans ce cas, il y aura toujours au moins une itération qui sera effectuée. Le C permet cette option par la construction do-while ( faire tant que ). Organigramme: Programme Bloc d instructions La syntaxe de l instruction est : do { instruction1; instruction2;.. while (<expression logique >); oui Condition vraie Suite du programme La condition est évaluée après le passage dans la boucle. Il faut noter l existence du ; après while(<expression logique >). Le bloc d'instruction(s) est d'abord exécuté. L'expression de test <expression logique > (entre parenthèses après while) est ensuite évaluée. Si elle est fausse (valeur 0), on sort de la boucle. Si elle est vraie, on itère, en ré-exécutant le bloc d'instruction(s), et ainsi de suite, tant que le test de boucle est vrai. De même, une boucle sans fin pourrait s'écrire comme: do { instruction(s) ; while (true);

37 Chap. 3 : Les structures de contrôle 33 Il est évident qu'on peut écrire avec un while (test avant) ou for, ce qu'on écrit avec un do-while (test après). Avoir les trois constructions facilite cependant la tâche du programmeur et l'écriture de programmes clairs et concis. Exemple 10 : Nous pouvons réécrire les instructions de l Exemple 9 comme suit: int compt=0; do { cout << compt << " " ; compt++; while (compt<=n ); Exemple 11 bool flag=true;... do {... if (...) flag=false;... while (flag==true);... Programme 3.8 : L application de l instruction do... while au programme 3.5 nous donne : #include <iostream> using namespace std; void main(){ char c ; int compt_a= 0,compt_b= 0, compt_tot= 0; cout << "ENTREZ UNE PHRASE: "; do { c=cin.get() ; if(c=='a') compt_a++; if(c=='b') compt_b++; compt_tot++ ; while(c!='\n'); cout <<"NOMBRE DE a: "<< compt_a << " de b : " << compt_b << " total : " << compt_tot; L exécution de ce programme donne cette fois-ci : ENTREZ UNE PHRASE: abracadabra magie NOMBRE DE a: 6, de b :2 et le total = 18 Il faut remarquer qu ici total = 18, et pas à 17 comme dans l exemple 3.6. En effet, après la phrase abracadabra magie, l utilisateur termine par Enter ( \n ) afin que la boucle s arrête. Et comme le bloc d instructions s exécute avant d arriver à la condition d arrêt while(c!='\n');, la variable compt_tot a été incrémentée par l introduction du caractère ( \n ) Instructions de branchement Les instructions de branchement transfèrent le contrôle du programme d une instruction à une autre. Nous examinons ici les instructions (mots réservés): Break ; continue ; goto ; return La dernière instruction return, sera traitée, pour des raisons pédagogiques, au chapitre des fonctions.

38 Chap. 3 : Les structures de contrôle Instruction break Elle ne peut s utiliser qu à l intérieur d une structure for, while, do while ou switch. Elle provoque l arrêt avant terme de ces instructions. Placée par exemple dans une boucle, l instruction break provoque l interruption immédiate de celle-ci et le contrôle est rendu à l instruction suivante. Pour illustrer notre propos, considérons par exemple les instructions suivantes contenant deux boucles : int i=0, j ; while (i<3){ for ( j=0 ; j<10 ; j++){ if (j== 2){ cout << endl; break; else cout << "i= " << i << " j= " << j <<" ; "; i++; L exécution de ce code nous donne le résultat suivant : i= 0 j= 0 ; i= 0 j= 1 ; i= 1 j= 0 ; i= 1 j= 1 ; i= 2 j= 0 ; i= 2 j= 1 ; En effet, chaque fois que j vaut 2, le break provoque l arrêt de l instruction for et rend le contrôle pour le i suivant du while Instruction continue Elle ne peut s utiliser qu à l intérieur d une structure for, while, do while. Alors que l instruction break stoppe complètement une boucle simple, l instruction continue permet de sauter un passage dans la boucle. L exécution reprend alors au prochain passage dans la boucle. Les instructions suivantes permettent de comprendre l effet de l instruction continue : int i=0, j ; while (i<3){ for ( j=0; j<4; j++){ if (j== 2){ i++; cout << endl; continue; else cout << "i= " << i << " j= " << j <<" ; "; L exécution de ce code nous donne le résultat suivant : i= 0 j= 0 ; i= 0 j= 1 ; i= 0 j= 3 ; i= 1 j= 0 ; i= 1 j= 1 ; i= 1 j= 3 ; i= 2 j= 0 ; i= 2 j= 1 ; i= 2 j= 3 ; En effet, chaque fois que j vaut 2, continue provoque un saut et passe à j=3 dans la boucle for

39 Chap. 3 : Les structures de contrôle Instruction goto L instruction goto provoque un saut à un endroit du programme repéré par une étiquette (label). Le programme continue alors à l instruction qui se trouve à cet endroit-là. Cette instruction peut parfois être utile, notamment dans les traitements d'erreurs. Mais il est fortement déconseillé de l'utiliser car son emploi abusif amène facilement à des programmes peu structurés et souvent illisibles. Sa syntaxe est la suivante : goto étiquette; où étiquette est une étiquette marquant la ligne destination dans la fonction. Les étiquettes sont simplement déclarées avec la syntaxe suivante : étiquette: Voici un ensemble d instructions qui illustre le fonctionnement de l instruction goto: int i=0, j ; while (i<3){ for ( j=-2; j<4; j++){ if (j== 0) else i++; erreur : cout << "Erreur car j =0 "; L exécution de ce code nous donne le résultat suivant : i=0 j=-2 i/j=0.00 i=0 j=-1 i/j=0.00 Erreur car j = 0 Ce qu il faut au moins retenir : goto erreur; cout << "i= " << i << " j= " << j <<" i/j " << (float)i/j << endl; 1) Il est recommandé, afin de faciliter la lecture et le "débogage", de ne mettre qu'une seule instruction par ligne dans la source du programme. Grâce à l'indentation des lignes, on fera ressortir la structure syntaxique du programme. Il est aussi recommandé de commenter les programmes et d éviter les commentaires triviaux. 2) if (i= =j){ // pas i=j car c est un test et pas une affectation 3) int i; cin >> i ; switch (i) { case valeur1 : ensemble_instruction1; break; 4) Les trois structures de contrôle d'itérations : char i; cin >> i ; switch (i) { case 'valeur1' : ensemble_instruction1; break; for (initialis. ; (?test_vrai); itération) { instruction 1; instruction 2; while (?test_vrai) { instruction 1; instruction 2; itération ; do { instruction 1; instruction 2; itération ; while(?test_vrai);

40 Chap. 3 : Les structures de contrôle 36 Exercices 3.0. Qu affiche ce code à l écran? int i=1; while(i<5) cout << "Dans while " << i << endl; i++; 3.1. Le test suivant : if( choix == o O ) peut-il remplacer if( choix == o choix== O ) et pourquoi? 3.2. Que se passe-t-il si on retire tous les "break" de l exemple 7 et que la valeur de la variable choix est égale à 1? 3.3. Ecrire un programme dont le rôle est de saisir 3 nombres réels au clavier et les afficher par ordre croissant Ecrire un programme qui calcule les racines d'un polynôme du second degré à coefficients réels. Examinez toutes les possibilités (racines réelles, complexes, doubles, infinité ou inexistence de solutions) Ecrire un programme qui calcule les 100 premiers nombres premiers Ecrire un programme qui calcule le plus grand commun diviseur (PGCD) de deux nombres entiers positifs par l'algorithme d'euclide Ecrire un programme qui calcule et affiche la factorielle d un nombre entre 1 et 10. Tant que le nombre introduit est <=0 ou > 10, redemandez l introduction de l entier Ecrire un programme qui lit N nombres entiers au clavier et qui affiche leur somme, leur produit et leur moyenne. Choisissez un type approprié pour les valeurs à afficher. Le nombre N est à entrer au clavier. Résolvez ce problème en utilisant, a) while, b) do - while, c) for. Laquelle des trois variantes est la plus naturelle pour ce problème? 3.9. Modifiez l exercice 3.7.en ne demandant plus N, mais que la suite de chiffres non nuls entrés au clavier soit terminée par zéro Ecrire un programme qui calcule et affiche la Table de multiplication par 2, par 5 et par 9. Exemple de solution : Table de 2 : 2 * 0 = 0 2 * 1 = 2 2 * 2 = 4 2 * 3 = 6 2 * 4 = 8 2 * 5 = 10 2 * 6 = 12 2 * 7 = 14 2 * 8 = 16 2 * 9 = 18 2 * 10 = 20

41 Chap. 3 : Les structures de contrôle Programmez un jeu où l'ordinateur choisira un nombre aléatoire entre 0 et 100 que vous devez deviner. Pour vous aider, l'ordinateur vous dira si vous êtes trop haut ou trop bas. Dès que vous l'aurez trouvé, il vous dira combien de coups vous avez dû jouer pour arriver à la bonne solution Calculez le N ième terme U N de la suite de FIBONACCI qui est donnée par la relation de récurrence: U 1 =1 U 2 =1 U N =U N-1 + U N-2 (pour N>2) Déterminez le rang N et la valeur U N du terme maximal que l'on peut calculer si on utilise pour U N le type: - int - long - double - long double Ecrire un programme qui calcule la série X * 3! X 2 * 5! X 3 * 7! X 4 * 9! S = * 2 2 * 4 3 * 8 4 * 16 L utilisateur introduira la valeur de X et le nombre de termes à prendre en compte. Le calcul du N ième terme se fera à partir du N-1, Il n est pas demandé de chercher le terme général.

42 Chapitre 4: Les tableaux et les chaînes de caractères 4.1. Les tableaux Les tableaux sont certainement les variables structurées les plus populaires. Un tableau est une collection de variables de même type, appelées éléments ou composantes du tableau. Le C++ alloue une zone contiguë de la mémoire lors de la déclaration d un tableau. En effet, la dimension maximale du tableau doit être connue avant son utilisation. Cette dimension est une CONSTANTE placée entre [ ] et une fois déclarée, on ne peut redimensionner un tableau Tableaux à une dimension Déclaration: Type Nom_Tableau[dim]; Nom_Tableau[0] Nom_Tableau[1]. Nom_Tableau[dim-1] Pour définir un tableau on utilise un type : le type des composantes du tableau, un identificateur : le nom du tableau, entre crochets [] : la dimension maximale du tableau (constante). Remarque : Nom_Tableau est un identificateur qui doit correspondre aux restrictions définies auparavant. Exemple1 int Tab1[10]; // dim=10 float Tab2[20]; char Tab3[2*15]; // dim=2*15 Cette déclaration signifie que le compilateur réserve 10 places en mémoire de type entier pour ranger les éléments du tableau Tab1, 20 réels pour Tab2 et 30 caractères pour Tab3. dim, dimension du tableau, est nécessairement une valeur numérique constante (10, 20, 2*15=30) et ne peut être en aucun cas une combinaison des variables du programme. Utilisation: Un élément du tableau est repéré par son indice. En C++, les tableaux commencent à l'indice 0. L'indice maximum est donc dim-1. Appel: Nom_Tableau[indice] Exemple2 Tab1[0] = 3; Tab2[3] = 1.015; Tab3[6] = C ; Le nom d'un tableau (Tab1, Tab2, Tab3) correspond à l'adresse mémoire du premier élément du tableau (Tab1 est équivalent à &Tab1[0], ). Les adresses des autres composantes sont calculées (automatiquement) relativement à cette adresse. Nous avons défini Tab1 comme un tableau avec dix composantes, auxquelles on peut accéder par: Tab1[0], Tab1[1],., Tab1[9].

43 Chap. 4 : Les tableaux et les chaînes de caractères 39 Tous les éléments d'un tableau ne sont pas forcément définis. D'une façon générale, les tableaux consomment beaucoup de place en mémoire. On a donc intérêt à les dimensionner au plus juste Tableaux à deux dimensions Les tableaux à deux dimensions ou matrices, sont rangés ligne par ligne et considérés comme des vecteurs de lignes. L accès aux composantes est effectué par des doubles crochets. Déclaration: Type Nom_Tableau [dim1][dim2]; Nom_Tableau [0][0] Nom_Tableau [0][1] Nom_Tableau [0][dim2-1] Nom_Tableau [1][0] Nom_Tableau [dim1-1][0] Nom_Tableau [dim1-1][dim2-1] Exemple3: int Tab12[4][5]; float Tab34[2][10]; char Tab_Char[5][3]; //déclare un tableau de 5*3=15 caractères Utilisation : Un élément du tableau est repéré par ses indices. En C/C++ les tableaux commencent aux indices 0. Les indices maxima sont donc dim1-1, dim2-1. Appel : Nom_Tableau [indice1][indice2] Exemple4: Tab12 [2][4] = 25; Tab34 [0][5] = 2.79; Initialisation et réservation automatique Lors de la déclaration d'un tableau, on peut initialiser ses composantes en indiquant la liste des valeurs respectives entre accolades. Exemple5 int Tab_A[5] = {10, 20, 30, 40, 50; float Tab_B[5] = { 10.1, 70.3, 30.5, 20.0, 50.4 ; int C_Tab[10] = {1, 1, 0, 1, 1, 1, 0, 1, 0, 1; int D_Tab[] = {1, 5, 3, 21; float E_Tab[2] = {1.1, 5.0, 1.2, 1.9; // erreur int Deux_Dim[2][3] = {{1,5,7,{8,4,3; //2 lignes et 3 colonnes Tab_A définit un tableau du type int de dimension 5. Les 5 composantes sont initialisées par les valeurs respectives 10, 20, 30, 40, et 50. On peut accéder à la première composante du tableau par Tab_A[0], à la deuxième composante par Tab_A[1],..., à la dernière composante par Tab_A[4]. Il faut évidemment veiller à ce que le nombre de valeurs dans la liste corresponde à la dimension du tableau. Si la liste ne contient pas assez de valeurs pour toutes les composantes, les composantes restantes sont initialisées à zéro. Mais si les valeurs dans la liste dépassent la dimension du tableau (E_Tab), une erreur se produit lors de l accès.

44 Chap. 4 : Les tableaux et les chaînes de caractères 40 Si la dimension n'est pas indiquée explicitement lors de l'initialisation, alors le compilateur réserve automatiquement le nombre d'octets nécessaires. Ainsi pour D_Tab, le compilateur lui réserve une dimension de quatre entiers car l'initialisation est faite à la déclaration. Programme 4.1 : Ecrire un programme qui lit la dimension N (<= NE_Max=10) d'un tableau T du type float, remplir le tableau par des valeurs entrées au clavier. Calculer et afficher ensuite la somme des éléments du tableau. #include <iostream> using namespace std; void main() { const int NE_Max =10 ; float T[NE_Max],Somme = 0.0; int N; Programme 4.1 cout << "Nombre d elements a saisir inferieur a " << NE_Max<<endl; cin >>N; // saisie des nombres cout << "SAISIR " << N << " NOMBRES SEPARES PAR RETURN: \n"; for(int i=0;i<n;i++) { cout << "T["<< i+1 <<"] = "; cin >> T[i]; Somme += T[i] ; cout << "\nla Somme = " << Somme << endl; Programme 4.2 : Ecrire un programme qui affiche les éléments du tableau à deux dimensions suivant : int A[3][5] = {{ 0, 1, 2, 3, 4, {10,11,12,13,14, { 20,21,22,23,24 ; #include <iostream> using namespace std; void main() { int A[3][5] = { { 0, 1, 2, 3, 4, {10,11,12,13,14,{ 20,21,22,23,24 ; for(int i=0;i<3;i++){ for(int j=0;j<5;j++){ cout << "A[" << i+1 <<"][" << j+1 << "]= " << A[i][j] << "; "; cout << endl ; Programme 4.2 Important! L'opérateur d'affectation ne peut affecter un tableau à un autre tableau : int t1[10], t2[10]; t1 = t2; // le compilateur rejettera cette instruction Une telle affectation ne peut se réaliser qu'à l'aide d'une procédure qui réalisera l'affectation élément par élément. En effet, un identificateur ayant le type tableau (t1 et t2) est converti en une valeur constante, on ne peut donc rien lui affecter.

45 Chap. 4 : Les tableaux et les chaînes de caractères Les chaînes de caractères Déclaration de chaînes de caractères En C++ une chaîne de caractères peut être traitée et manipulée à travers un tableau de caractères à une dimension (vecteur de caractères), avec des déclarations dont la syntaxe est de type : char Ident[dim]; //Ident : Nom de la chaîne de caractères Mais il existe aussi un type spécial string (le mot anglais pour une chaîne de caractères), dont la syntaxe est de type : string Ident; // Il faut inclure <string> Initialisation de chaînes de caractères a) char Ident[dim]; char s[10] = "bonjour!"; 'b' 'o' 'n' 'j' 'o' 'u' 'r' ' ' '!' '\0' s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] Le caractère nul '\0' (null terminator), de code ASCII 0, est un caractère de contrôle qu il ne faut pas confondre avec le caractère affichable '0', lequel est codé par le nombre ASCII 48. Il doit être placé obligatoirement en fin de chaîne. Sans lui, la chaîne n'a pas de fin. Une lecture de la chaîne pourrait donc continuer jusqu'au prochain caractère nul en mémoire, et donc bien après la dimension maximale. Dans l exemple, '\0' est ajouté automatiquement par le compilateur, car le nombre de caractères dans "bonjour!" est inférieur à la dimension du tableau s. char S[] = {'H','e','l','l','o','\0'; 'H' 'e' 'l' 'l' 'o' '\0' S[0] S[1] S[2] S[3] S[4] S[5] Le tableau S est initialisé par le programmeur et '\0' est ajouté par lui même. char S[6] = "Hello"; 'H' 'e' 'l' 'l' 'o' '\0' S[0] S[1] S[2] S[3] S[4] S[5] '\0' est ajouté automatiquement par le compilateur, car le nombre de caractères (5) dans "Hello" est inférieur à la dimension du tableau S (6). char S[8] = "Hello"; 'H' 'e' 'l' 'l' 'o' '\0' ' ' ' ' S[0] S[1] S[2] S[3] S[4] S[5] S[6] S[7] '\0' est ajouté automatiquement par le compilateur à la fin de "Hello";

46 Chap. 4 : Les tableaux et les chaînes de caractères 42 Par exemple le programme suivant affiche Hello: #include <iostream> using namespace std; void main() { char S[8]= "Hello"; for(int i=0; i<8; i++){ cout << S[i] << endl; Programme 4.3 Si par contre la dimension de S est inférieure à la taille réelle de "Hello", c est-à-dire inférieure à 6, (5+1 pour '\0'), selon le compilateur, une erreur se produit pendant la compilation ou pendant l exécution. b) string Ident; // Il faut inclure <string> Cette construction est équivalente à string Ident = ""; ce qui revient à dire que par défaut une chaîne est créée vide. Il existe toutefois de nombreuses autres façons d initialiser un string string s1 = "Bonjour a vous"; string s2 = s1; // s2 contient " Bonjour a vous " string s3(4, 'x'); // équivaut à string s3 = "xxxx" string s4(s1, 4, 8); // s4 contient "our a vo" Exemple 6: #include <string > string ST = "Salut"; for (int i=0;i<5;i++) { cout << ST[i] << " "; // affichera : S a l u t Exemple 7 : #include <string > string Phrase; while ( cin >> Phrase ) cout << "Dans Phrase il y a: " << Phrase << '\n'; cout << "ok: Plus rien : bye!\n"; Si l utilisateur introduit : Le monde est un livre Le résultat sera : Dans Phrase il y a: Dans Phrase il y a: Dans Phrase il y a: Dans Phrase il y a: Dans Phrase il y a: Le monde est un livre Pouvez-vous nous dire quand le programme affichera " ok: Plus rien : bye! "? Expliquez.

47 Chap. 4 : Les tableaux et les chaînes de caractères Précédence alphabétique et lexicographique La précédence des caractères dans l'alphabet d'une machine est dépendante du code de caractères utilisé. Pour le code ASCII, nous pouvons constater l'ordre suivant:...,0,1,2,...,9,...,a,b,c,...,z,...,a,b,c,...,z,... Les symboles spéciaux (',+,-,/,{,],...) et les lettres accentuées (é,è,à,û,...) se trouvent répartis autour des trois grands groupes de caractères (chiffres, majuscules, minuscules). Leur précédence ne correspond à aucune règle d'ordre spécifique. Relation de précédence De la précédence alphabétique des caractères, on peut déduire : '0' est inférieur à 'Z' et noter '0' < 'Z' car dans l'alphabet de la machine, le code du caractère '0' (ASCII: 48) est inférieur au code du caractère 'Z' (ASCII: 90). Précédence lexicographique des chaînes de caractères En nous basant sur cette relation de précédence alphabétique des caractères, nous pouvons définir une précédence lexicographique pour les chaînes de caractères. Cette relation de précédence suit l'ordre du dictionnaire et est définie de façon récurrente: a) la chaîne vide "" précède lexicographiquement toutes les autres chaînes ; b) la chaîne A = "a 1 a 2... a p " (p caractères) précède lexicographiquement la chaîne B = "b 1 b 2... b m " (m caractères) si l'une des deux conditions suivantes est remplie: 1) 'a 1 ' < 'b 1 ' 2) 'a 1 ' = 'b 1 ' et "a 2 a 3... a p " précède lexicographiquement "b 2 b 3... b m " Exemple 8 "ABC" < "BCA" "ABC" < "B" "Abc" < "abc" "ab" < "abcdz" car 'A'<'B' car 'A'<'B' car 'A'<'a' car " " < "cd" " ab" < "ab" car ' '<'a' (le code ASCII de ' ' est 32, et le code ASCII de 'a' est 97) La classe string fournit les opérateurs suivants : Égal à == ; Non égal à!= ; Affectation = ; Addition et affectation += Concaténation des chaînes de caractères ou addition + Dans le programme 4.4 qui suit, si on déclare les chaînes comme des tableaux de caractères : char ST1[4] = "ABC"; char ST2[4] = "DEF"; il n est pas correct d affecter ou de concaténer comme le montre le programme (ST1 = ST2, ST12 = ST1+ST2 ). En effet, comme les chaînes sont déclarées comme des tableaux, il n'est pas permis de

48 Chap. 4 : Les tableaux et les chaînes de caractères 44 faire des opérations d'affectations ou d additions sur celles-ci. Elles peuvent être initialisées avec = mais pas affectées avec =. Ces opérations peuvent se faire caractère par caractère. #include <iostream> #include <string> using namespace std; // traitement de string /* utilisation de l espace de nommage std pour importer les symboles de la bibliothèque standard C++ */ void main( ) { string ST1 = "ABC", ST2 = "DEF", ST12, ST3, ST4; cout<< "ST1 = " << ST1 << "\t Et ST1[0] = " << ST1[0] << endl; cout<< "ST2 = " << ST2 << "\t Et ST2[1] = " << ST2[1] << endl; cout << "\nle plus grand est : "; if (ST1>ST2) cout<< ST1; else cout << ST2; ST12 = ST1+ST2; // concaténation = fusion des deux chaînes cout<< "\n\nst12 : ST1+ ST2= " << ST12 << endl; cout << "\nposition de la premiere occurrence de DEF dans ST12 = "; cout << ST12.find("DEF"); ST12 += " PLUS"; cout<< "\n\nst12 : ST12+ PLUS= " << ST12 << endl; ST1=ST2; cout<< "\ncopie ST1=ST2 " << endl; cout<< "ST1 = " << ST1 << " et ST2 = " << ST2 << endl; cout <<"\naffecte ST12[1],,ST12[4] a ST3 : \t\t\t ST3= " ; ST3.assign(&ST12[1], &ST12[5]); cout << ST3 << endl; cout <<"Affecte les deux premiers caracteres de ST3 a ST4 : \t ST4= " ; ST4.assign(ST3, 0, 2); cout << ST4 << endl; cout << "Reinitialise ST12 avec des 'B' : \t\t\t ST12= "; ST12.assign(4, 'B'); cout << ST12 << endl; ST12.append("AA"); cout << "ST12.append(AA) :... \t\t\t... ST12= "; cout << ST12 << endl; ST12.insert(1, "bcd"); cout << "ST12.insert(1, bcd):... \t\t\t... ST12= "; cout << ST12 << endl; ST12.insert(5, "CC").insert(7, "DD").insert(10, "FF"); cout << "ST12.insert(5, CC).insert(7, DD).insert(10, FF)... ST12= "; cout << ST12 << endl; Programme 4.4 ST12 += "_FIN"; cout << "ST12 += _FIN... \t... ST12 = "; cout << ST12 << endl;

49 Chap. 4 : Les tableaux et les chaînes de caractères 45 Le résultat du programme 4.4 est le suivant : ST1 = ABC ST2 = DEF Et ST1[0] = A Et ST2[1] = E Le plus grand est : DEF ST12 : ST1+ ST2= ABCDEF Position de la premiere occurrence de DEF dans ST12 = 3 ST12 : ST12+ PLUS= ABCDEF PLUS Copie ST1=ST2 ST1 = DEF et ST2 = DEF Affecte ST12[1],..,ST12[4] a ST3 : ST3= BCDE Affecte les deux premiers caracteres de ST3 a ST4 : ST4= BC Reinitialise ST12 avec des 'B' : ST12= BBBB ST12.append(AA) : ST12= BBBBAA ST12.insert(1, bcd): ST12= BbcdBBBAA ST12.insert(5, CC).insert(7, DD).insert(10, FF)... ST12= BbcdBCCDDBFFBAA ST12 += _FIN ST12 = BbcdBCCDDBFFBAA_FIN find est une méthode (fonction) qui permet de rechercher la sous-chaîne correspondant au motif passé en paramètre. Elle retourne l'indice de la première occurrence de ce motif dans la chaîne de caractères, ou une valeur quelconque si le motif n'y apparaît pas. Assign est une autre méthode qui permet d affecter un certain nombre de caractères d une chaîne à une autre. append et insert sont d autres méthodes de manipulation sur les string. Il faut noter que le nombre de méthodes est conséquent, comme par exemple des recherches dans les chaînes de caractères grâce aux méthodes find, find_first_of, find_last_of, et qu il nous est impossible de toutes les détailler dans ce syllabus. Programme 4.5 : Ecrire un programme qui vérifie que le nom du fichier introduit par l utilisateur possède l'extension.dat, et tant qu il n est pas conforme, on redemande d introduire le nom #include <iostream> #include <string> using namespace std; // Chaîne de caractères void main( ) { string nom; int len, size; bool rep = false; Programme 4.5 do{ cout << "\nnom du fichier.dat : " ; cin >> nom; len = nom.length(); // nombre de caractères dans nom size = nom.size(); // nombre de caractères dans nom cout << "size = " << size << " len = " << len; if ( nom[len-4]=='.' && nom[len-3]=='d' && nom[len-2]=='a' && nom[len-1]=='t'){ cout << "\nextension OK"; rep = true; else cout << "\nextension Not OK"; cout << "\nvoici votre nom : " << nom << endl; while(rep==false);

50 Chap. 4 : Les tableaux et les chaînes de caractères 46 Ce qu il faut au moins retenir : Un tableau est une collection de variables de même type et qui commence à l'indice 0. L'indice maximum est donc dim-1 si on déclare un tableau Tab[dim]. L affectation d un tableau à un autre est interdite de la manière suivante : int TabA[]= {1,2,3, TabB[]={5,6,7; TabA = TabB; &Tab[0] est équivalent à Tab Une chaîne de caractères se comporte différemment selon le type de déclaration : string TabA="ABC"; string TabB ="def " ; TabA=TabB; // Correcte char TabA[4]= "ABC"; char TabB[4] ="def" ; TabA=TabB; // Non correcte Pour cela, il faut inclure <string> Exercices 4.1. Les déclarations des tableaux suivants sont-elles correctes? Pourquoi? Corrigez les déclarations fausses. int TabA[5] = {0, 2, 3, 4, 5; char tab[5] = 'ABCD '; char ST[7] = "Bonjour"; char a[11]= " \0"; char b[] = "un\ndeux\ntrois\n"; char f[] = "Cette " "phrase" "est coupée"; 4.2. Les affectations suivantes sont-elles correctes? Pourquoi? char T,S = 'K', A[10] = "Salut", B[10]; string C, D="Toto" ; a) T = S; b) T = &S; c) B=A; d ) D= C; e) C= D; f) C= A; g) B= D; 4.3. Écrire un programme qui range au maximum (taille Nmax ) 20 nombres entiers saisis au clavier dans un tableau et qui calcule sa moyenne Écrire un programme qui supprime le premier et le dernier élément d un vecteur. vecteur initial : Tab sup. bords sup. bords Écrire un programme qui supprime le milieu du tableau et ajoute son double au début. vecteur initial : Tab sup. Aj sup. Aj Codez un programme de tri à bulles d'un vecteur de strings.

51 Chap. 4 : Les tableaux et les chaînes de caractères Codez un programme de recherche dichotomique d'un nombre dans un vecteur de strings rangés par ordre croissant On dispose de deux tableaux A et B, de dimensions respectives N et M, triés par ordre croissant. Fusionnez les éléments de A et B dans un troisième tableau C trié par ordre croissant. Entrelacez A et B dans un quatrième tableau D Ecrire un programme qui construit et affiche une matrice carrée unitaire U de dimension N. Une matrice unitaire est une matrice, telle que: Uij = 1 si i=j et 0 sinon Écrire un programme qui permet de supprimer toutes les valeurs V>7 du tableau T: T Complétez le code pour que L1 et/ou L2 puissent contenir du texte (des caractères et des espaces). (ex: "bonjour à tous"). string L1, L0; // L1: un ou + Espaces char L2[100]; // L2: un ou + Espaces cout << " L0: " ; cin >> L0; cout << "Première ligne L1: " ; cout << "\n Deuxième ligne L2: " ; On désire réaliser la gestion d un réseau routier par l intermédiaire de tableaux en reliant N villes principales de Wallonie dont on connaît les distances qui séparent les villes entre elles. Quelques idées de distances sur autoroute entre les villes principales de Wallonie : Bruxelles Namur : 63 km Bruxelles Liège : 97 km Bruxelles Charleroi : 62 km Bruxelles Mons : 68 km Namur Charleroi : Namur Liège : Namur Mons : Charleroi Liège : Charleroi Mons : Liège Mons : 37 km 65 km 74 km 94 km 50 km 130 km On définira Villes un tableau de chaîne de caractères qui contiendra toutes les villes de notre réseau. On définira ensuite un tableau à deux dimensions Distances[ville1,ville2] qui contiendra les distances entre deux villes du tableau Villes. On supposera que les distances sont toutes distinctes entre elles et ont des valeurs entières. 1. écrire le code d initialisation des tableaux Villes et Distances 2. écrire le code qui permet d afficher la distance entre deux villes du tableau 3. écrire le code qui permet de trouver les deux villes les plus proches

52 Chapitre 5 : Les fonctions 5.1. Introduction Jusqu'ici, nous n avons utilisé que la fonction principale main(). Pour une programmation plus conséquente, nous obtenons ainsi de longues listes d'instructions, peu structurées et par conséquent peu compréhensibles. En plus, il faut souvent répéter les mêmes suites de commandes dans le texte du programme, ce qui réduit la lisibilité de ce dernier. Dans la plupart des langages de programmation le principe de modularité est fondamental. Il permet de subdiviser les programmes en sous-programmes, fonctions ou procédures plus simples et plus compactes. A l'aide de ces structures, nous pouvons modulariser nos programmes pour obtenir des solutions plus élégantes et plus efficientes. La structuration de programmes en sous-programmes ou en modules se fait, entre autre, à l'aide de fonctions. Quand on a un problème, on commence par le décomposer en un ensemble de petits problèmes distincts ou modules, plus simples à traiter, jusqu'à obtenir des tâches élémentaires et faciles à spécifier et à mettre en œuvre. Dans ce contexte, une fonction est un module qui désigne une entité de données et d'instructions qui fournissent une solution à une partie bien définie d'un problème. Une fonction peut faire appel à d'autres fonctions, leur transmettre des données et recevoir des données en retour. L'ensemble des modules ainsi reliés doit alors être capable de résoudre le problème global. Dans ce syllabus, nous insistons sur le fait qu un programme est constitué d'un ensemble de fonctions, l'une d'entre elles étant la fonction main() ou programme principal. Chaque fonction représente un morceau de programme logiquement cohérent dans lequel on décrit un ensemble d actions à effectuer. Nous allons, au cours de ce chapitre, découvrir comment nous pouvons définir et utiliser nos propres fonctions et ce que cette notion nous apporte comme réel confort au niveau de la programmation, de la lisibilité, Voici quelques avantages d utilisation des fonctions : meilleure lisibilité ; diminution du risque d'erreurs ; réutilisation des modules ; amélioration du débogage et de la maintenance ; favorisation du travail en équipe Définition de fonctions En général, le nom d'une fonction apparaît à trois endroits dans un programme: 1) lors de la définition 2) lors de la déclaration 3) lors de l'appel Comme le langage C++ est déclaratif, normalement tout objet C++ doit être déclaré avant d'être utilisé. Ceci s applique à toute fonction qui pour pouvoir être utilisée, doit être définie voire

53 Chap. 5 : Les fonctions 49 déclarée. Elle porte un nom, qui est un identificateur semblable à celui des variables. Elle peut avoir ou ne pas avoir de paramètres qui ont chacun un type spécifique selon les besoins. Elle renvoie zéro (mot-clé void) ou une valeur de retour, dont le type doit être également spécifié. La structure d'une fonction est de la forme suivante : Type_retourné nom_fonction(liste_paramètres_typés) {... // Corps de la fonction. return(valeur); // On peut aussi écrire : return valeur; Si Type_retourné vaut void (qui signifie "vide" en anglais), alors la fonction ne renvoie pas de valeur. Dans ce cas, soit on: n'utilise pas d'instruction return(valeur) comme dans l'exemple de la fonction Affiche ci-dessous. utilise une telle instruction, mais sans (valeur) : return ; Si Type_retourné est omis lors de la définition de la fonction, le compilateur suppose que la fonction retourne une valeur de type int. Considérons une nouvelle fonction Affiche, qui a pour rôle d afficher les paramètres passés en argument de la fonction. Sa définition peut se faire comme suit: void Affiche( int x, float y) { //En-tête de la fonction cout << "\nles valeurs des parametres sont x= " << x << " et y = " << y << endl; Type_retourné : void, nom_fonction : Affiche, liste_paramètres_typés : int x, int y, return : pas de return car Type_retourné : void. La première ligne de la définition (en-tête de la fonction) contient : Affiche : un identificateur correspondant au nom de la fonction. void : le type de valeur renvoyée, cela indique que la fonction, après avoir effectué sa tâche, ne renvoie rien à toute fonction qui a appelé Affiche. (int x, float y) : liste de paramètres, chacun a un type et un nom. Les parenthèses sont obligatoires même s il n y a pas de paramètres. Le corps de la fonction dans, cet exemple, ne contient qu une seule instruction. L'imbrication de fonctions n'est pas autorisée: une définition de fonction ne doit pas contenir d autres définitions de fonctions. L exemple suivant n est pas autorisé : void fonction1() { cout << " fonction1 "; void fonction2( ) { cout << " fonction2 ";

54 Chap. 5 : Les fonctions Instruction return Considérons maintenant une nouvelle fonction Somme, qui additionne deux entiers passés comme paramètres de la fonction, et retourne la somme. La définition de cette fonction est: int Somme(int x, int y) { return (x + y) ; //En-tête de la fonction Type_retourné : int, nom_fonction : Somme, liste_paramètres_typés : int x, int y, return : x+y. Le corps de la fonction dans, cet exemple, ne contient que le mot-clé return. La valeur retournée est une expression ou une valeur (ici : x+y). On remarquera que cette fonction ne modifie pas la valeur des paramètres entrés x et y. Ce n'est pas toujours le cas, il y a des fonctions qui modifient certains de leurs paramètres (voir plus loin). Quand un paramètre d'entrée n'est pas modifié par la fonction, il est intéressant de faire précéder son type par le mot-clé const. Cette convention permet une vérification par le compilateur de la nonmodification de ce paramètre dans le code de la fonction et, évite ainsi des sources potentielles d'erreur. La fonction Somme peut donc s écrire aussi comme suit : int Somme(const int x, const int y) { return (x+y) ; // retourne le résultat int de Somme à la fonction appelante Le mot-clé return met fin à l exécution des instructions d une fonction et rend le contrôle du programme à l instance appelante. Considérons la fonction Sortie, int Sortie (const int x, const int y) { if (x>y) return x; else return y; cout << "x= " << x << " y = " << y << " et somme = " << x+y ; Cette fonction possède deux points de sortie. Soit en retournant x si (x>y), soit en retournant y dans le cas contraire. Notons que l instruction pour afficher x,y,x+y ne sera jamais exécutée. En effet, return met fin à l exécution des instructions d une fonction et rend le contrôle à la fonction appelante.

55 Chap. 5 : Les fonctions Appel et déclaration de fonctions La déclaration d une fonction n est pas obligatoire si sa définition se trouve plus haut que son appel dans le programme. Mais si nous désirons définir les fonctions n importe où dans le programme sans nous soucier de l ordre de définitions et appels, il faut déclarer les fonctions. Une déclaration de fonction, qui se termine par un point-virgule, fournit des indications sur le type, le nom et sur d éventuels paramètres. Mais contrairement à une définition, une déclaration de fonction ne fait que donner au compilateur des renseignements sur l existence d une entité et n en crée pas de nouvelle. Les fonctions, une fois définies, peuvent être appelées dans le corps d'autres fonctions, ou de la fonction elle-même (récursivité). La définition ou la déclaration d une fonction doit se faire avant l appel de celle-ci. Pour cela, dans une expression, on placera le nom de la fonction ainsi que les valeurs des paramètres réels (lors de l'appel) de cette fonction. Ces paramètres peuvent bien sûr (mais ne doivent pas obligatoirement) avoir un nom différent de celui employé lors de la définition de la fonction. Seul le nombre, l ordre et le type des paramètres doivent correspondre à celui de la définition. Par exemple, un programme principal pourra faire appel à la fonction Somme, définie dans la section précédente, comme suit: #include <iostream> using namespace std; int Somme (const int x, const int y); void main( ) { //Déclaration de la fonction //Programme de calcul de la somme des deux entiers int S, i; // Variables locales à main S = Somme (5,6); //Appel de Somme et stockage du résultat dans S. cout << "La Somme de 5 et 6 : " << S; for (i=0; i<=10; i++) cout << "\n 2 x " << i << " = " << Somme(i,i); Dans ce programme, nous appelons plusieurs fois la fonction Somme et notamment au cœur d'une boucle for. Ceci est tout à fait légal en C++. La troisième ligne du programme signale au compilateur que nous allons utiliser une fonction Somme, à deux paramètres constants et entiers, fonction qui renvoie un entier: c'est ce qu'on appelle un prototype ou déclaration de fonction, indispensable au compilateur. Un appel à une fonction peut donc être utilisé dans une expression: c'est une force du C++, car cela facilite la lisibilité du programme (si on n'en abuse pas!). Les deux programmes (Programme 5.1) sont équivalents et montrent quand il faut utiliser la déclaration des fonctions.

56 Chap. 5 : Les fonctions 52 // Version1 #include <iostream> using namespace std; void Affiche (int x, int y); int Somme (const int x, const int y); void moyenne(const int x, const int y) ; void main(void) { int i; for (i=0; i<=10; i++) { Affiche (i, Somme(i,i)) ; moyenne( i, i*i) ; void Affiche (int x, int y){ cout << "\n 2 * " << x << "=" << y ; int Somme(const int x, const int y) { return (x+y); void moyenne(const int x, const int y) { float Moy ; Moy = (x+y)/2.0 ; cout << "la moyenne est : " << Moy <<endl ; // Version2 #include < iostream> using namespace std; int Somme(const int x, const int y){ return (x+y); void Affiche (int x, int y){ cout << "\n 2 * " << x << "=" << y ; void moyenne(const int x, const int y) { float Moy ; Moy = (x+y)/2.0 ; cout << "la moyenne est : " << Moy <<endl ; void main(void) { int i; for (i=0; i<=10; i++) { Affiche (i, Somme(i,i)) ; moyenne( i, i*i) ; Programme 5.1 Il faut remarquer que la fonction Somme est passée comme paramètre de la fonction Affiche lors de l appel de celle-ci. La différence entre les deux versions est, que dans la Version2, la définition des fonctions est avant leur appel, et donc leurs déclarations ne sont pas obligatoires, contrairement à la Version1. L exécution des deux programmes affiche le même résultat : 2 * 0 = 0 la moyenne est : 0 2 * 1 = 2 la moyenne est : 1 2 * 2 = 4 la moyenne est : 3 2 * 3 = 6 la moyenne est : 6 2 * 4 = 8 la moyenne est : 10 2 * 5 = 10 la moyenne est : 15 2 * 6 = 12 la moyenne est : 21 2 * 7 = 14 la moyenne est : 28 2 * 8 = 16 la moyenne est : 36 2 * 9 = 18 la moyenne est : 45 2 * 10= 20 la moyenne est : Passage de paramètres Avec la liste des paramètres d une part et l instruction return d autre part, une fonction dispose de deux moyens pour communiquer ou pour échanger des données avec d autres fonctions. L instruction return a déjà été traitée; dans cette section, nous allons approfondir l étude des paramètres des fonctions.

57 Chap. 5 : Les fonctions 53 Les paramètres d'une fonction acceptent les données de l'extérieur et déterminent les actions et le résultat de la fonction. Les valeurs de ces paramètres doivent être connues pour enclencher la fonction. Nous n'admettons donc pas des variables cachées non passées en paramètres (variables globales). En effet, c'est contraire à la lisibilité et à la modularité des programmes. Il ne faut pas non plus mettre des paramètres inutiles, qui pourraient être définis comme variables locales dans une fonction. Quand on veut définir une fonction, on réfléchit donc sérieusement à son interface nécessaire et suffisant: quels sont les paramètres d'entrée (non modifiables)? quel type a la valeur de retour? y a-t-il d'autres paramètres nécessaires? Soit des paramètres d'entrée à modifier, soit des paramètres de retour. Pour ce dernier point (paramètres de retour, c'est-à-dire modifiés par la fonction), nous aurons besoin, d'un passage différent des paramètres: le passage par référence (voir chapitre 6). En effet, le langage C++ propose deux modes de passages de paramètres: - le passage par référence, souvent caractérisé par le marqueur syntaxique & ; - le passage par valeur, dans tous les autres cas Passage de paramètres par valeur Le passage de paramètres par valeur est en C/C++ le mode standard de transmission des paramètres effectifs à une fonction. Si, par exemple, une variable (tableaux, pointeurs et références exceptés), apparaît en tant que paramètre réel d une fonction, alors la fonction appelée reçoit plus précisément une copie de la valeur de la variable passée comme paramètre. La fonction travaille donc sur un duplicata et non sur l original de la valeur transmise. Autrement dit, les fonctions n'obtiennent que les valeurs de leurs paramètres et n'ont pas d'accès aux variables elles-mêmes. Donc, les paramètres d'une fonction sont à considérer comme des variables locales qui sont initialisées automatiquement par les valeurs indiquées lors d'un appel. A l'intérieur de la fonction, nous pouvons donc changer les valeurs des paramètres sans influencer les valeurs originales dans les fonctions appelantes. #include <iostream> using namespace std; void Modifier(int v){ v = v *100; cout << "Modifier: v = "<< v; void main(){ int v = 5; Modifier(v); cout << "\n main: v = " << v; // Modifie la copie /* Affiche la valeur de v dans la fonction Modifier*/ // Variable locale à main() // Appel de la fonction Modifier /* Affiche la valeur de v après passage dans la fonction Modifier*/ Programme 5.2

58 Chap. 5 : Les fonctions 54 L exécution de ce programme s effectue de la manière suivante : 1. le programme commence son exécution, comme toujours, par la fonction main(), 2. v est initialisé à 5 puis injecté dans la fonction Modifier que l on enclenche, 3. la copie de v est modifiée dans la fonction, et est multipliée par 100, 4. à l intérieur de Modifier on affiche : Modifier: v = 500, 5. on retourne à la fonction main() juste après l exécution de la fonction Modifier, 6. dans main() on affiche : main: var = 5 Ceci montre que le changement effectué sur la variable à l intérieur de la fonction Modifier (500) est resté local à cette fonction. Lorsqu on retourne dans la fonction main(), la variable a récupéré sa valeur originale (5). Le changement dans Modifier n a aucune influence sur elle. Cela montre bien que la fonction n a manipulé qu une copie de la variable et non l originale. Un autre exemple classique est donné par le programme 5.3 et dont nous laissons au lecteur le soin d analyser les résultats. #include <iostream> using namespace std; void affiche (int, int); void echange (int, int); void main () { int i= 1, j=2; cout << " Dans main(): avant Appel de la fonction echange" << endl; affiche (i, j); cout << endl; cout << " Dans la fonction echange " << endl; echange (i, j); cout << endl; cout << " Dans main(), apres Appel de la fonction echange" << endl; affiche (i, j); void affiche (int a, int b) { cout << "\t\t Valeurs i = " << a << " j = " << b << endl; void echange (int a, int b) { int tmp; cout << "\tavant transformation" << endl; affiche (a, b); tmp = b; b = a; a = tmp; cout << "\tapres transformation" << endl; affiche (a, b); Programme 5.3

59 Chap. 5 : Les fonctions 55 L exécution nous donne : 1. Dans main(): avant Appel de la fonction echange Valeurs i = 1 j = 2 2. Dans la fonction echange Avant transformation Valeurs i = 1 j = 2 Apres transformation Valeurs i = 2 j = 1 3. Dans main(), apres Appel de la fonction echange Valeurs i = 1 j = Tableaux comme paramètres Les tableaux peuvent être passés comme paramètres de fonctions. Ils ne peuvent cependant pas être retournés comme résultat d'une fonction (par le mot-clé return). Pour déclarer un tableau comme paramètre d'une fonction, il suffit de l'exprimer dans la liste des paramètres. Ici, la longueur n'est pas indispensable, car elle sera définie lors de l'appel à la fonction. Il est souvent demandé de manipuler des tableaux et de garder le changement effectué. Tel est le cas, par exemple, lorsqu il faut trier un tableau. Supposons un tableau défini dans la fonction principale main() : int tab[10] = {5, 8, 3, 1, 9, 0, 4, 6, 7, 2 ; Nous souhaitons trier ce tableau afin d obtenir le résultat suivant : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 La fonction TriaBulles, utilise l algorithme du tri à bulles vu au cours. Pour que cette fonction trie convenablement le tableau, il faut lui communiquer, en plus du tableau, son nombre d éléments ou bien le nombre d éléments à trier. Déclaration : void TriaBulles(int tab[], int nbr_elem) ; Définition : void TriaBulles(int x[], int N) // X tab et N nbr_elem { int i, perm=1, tmp; // variables locales à TriaBulles while (perm==1) { perm =0; for (i=0;i<n-1;i++) { if(x[i] > x[i+1]) { tmp = x[i]; x[i] = x[i+1]; x[i+1] = tmp; perm = 1; OU void TriaBulles(int x[], int N) { int i, tmp; bool perm=true; while (perm) { perm =false; for (i=0;i<n-1;i++) { if(x[i]>x[i+1]) { tmp = x[i]; x[i] = x[i+1]; x[i+1] = tmp; perm = true;

60 Chap. 5 : Les fonctions 56 L appel de la fonction dans main() : #include... void main( ) { int i, K = 10, tab[10] = {5, 8, 3, 1, 9, 0, 4, 6, 7, 2 ; TriaBulles (tab, K); cout << "Vecteur trie :" << endl; for(i=0;i< Ki++) cout << tab[i] << ", "; cout << endl; Le résultat de l exécution, comme nous l attendons évidemment, est : Vecteur trie : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, Ce qu il faut remarquer : les noms des paramètres ne doivent pas forcément être les mêmes à la déclaration, à la définition et à l appel, mais correspondent par la position au niveau de leurs types ; les crochets du tableau lors de la déclaration sont obligatoires ; le passage du tableau lors de l appel se fait sans crochets. Mais ce qu il faut surtout noter : Un tableau passé comme paramètre d une fonction, garde les modifications effectuées dans la fonction et les transmet à la fonction appelante. En fait, les tableaux en C/C++ sont toujours transmis à une fonction par adresse ou référence et non par valeur, contrairement aux variables standards. La fonction appelée reçoit toujours, ce faisant, l adresse du début du tableau, c est-à-dire l adresse de son premier élément d indice zéro. L appel TriaBulles (tab, K); est équivalent à TriaBulles (&tab[0], 10);. Donc dans ce cas, on ne travaille pas sur une copie mais sur la variable elle-même puisqu on accède à son adresse. Plus de détails seront donnés au chapitre 6. Pour que cet exemple fonctionne pour un tableau de dimension quelconque initialisé par l utilisateur, la fonction main() deviendra : void main( ) { int const NMAX= 20; int tab[nmax], i, N; cout << "Donner un nombre (entre 1 et " << NMAX << ")!! "; cin >> N; for(i=0;i<n;i++) { cout << "nombre " << i+1; cin >> tab[i]; TriaBulles (tab, N); cout << "Vecteur trie :" << endl; for(i=0;i<n;i++) cout << tab[i] << ", "; cout << endl;

61 Chap. 5 : Les fonctions Visibilité des variables Jusqu à présent, nous n avons vu que des variables locales. Ces variables, déclarées au début d'une fonction ou de main(), ne sont connues et visibles qu à l'intérieur de la fonction où elles sont déclarées. Elles ne sont pas automatiquement initialisées (sauf si on le fait dans le programme) et elles perdent leur valeur à chaque appel à la fonction. Nous pouvons définir des variables globales qui sont déclarées au début du programme. Elles sont connues de toutes les fonctions du programme. Ces variables sont initialisées à 0 au début de l'exécution, sauf si on les initialise à une autre valeur. En général, les variables globales sont déclarées immédiatement derrière les instructions #include au début du programme. L exemple suivant montre quelques erreurs dues à la confusion de l utilisation de variables locales et globales : #include < iostream> using namespace std; int globale; // variable globale void fonc(int x); void main(void) { int i = 5, j; //locales à main float f = 2.8, g; d = 3.7; // (0) cout << " valeur de j= " << j ; // (1) cout << "\nglobale = " << globale ; // (2) fonc (i); void fonc(int v) { double d, f ; //locales à fonc (3) i++; // (4) globale --; // (5) f = 0.0; Explications : (0) : d est une variable locale à la fonction fonc et ne peut être initialisée dans main(). (1) : j variable locale à main() n est pas initialisée, donc le cout affiche n importe quelle valeur. (2) : ici ce n est pas une erreur car globale est une variable globale et est initialisée automatiquement. (3) : f est une variable locale à fonc différente de la variable locale à main() f. (4) : i ne peut être incrémenté ici car c est une variable locale à main(). (5) : globale peut être décrémenté car c est une variable globale connue dans toutes les fonctions du programme.

62 Chap. 5 : Les fonctions 58 Voici un programme qui trace la valeur des variables locales et celle d une variable globale. #include <iostream> using namespace std; int g; // variable globale void affichage(int un, int deux) { cout << un << " " << deux << " " << g << endl; void fonc(int un, int deux){ affichage(un, deux); un += 2; deux += 2; g += 2; affichage(un, deux); Programme 5.4 void main(void) { int i = 5, j; //locales à main affichage(i, j); j=10; fonc(i, j); affichage(i, j); Ce programme produit le résultat suivant : Conseils : Il faut faire attention à ne pas masquer involontairement des variables globales par des variables locales du même nom. Les variables globales sont à utiliser avec précaution car la modularité d'un programme peut en souffrir et la lisibilité peut en être diminuée. L'utilisation de variables globales devient inévitable, si plusieurs fonctions qui ne s'appellent pas ont besoin des mêmes variables ; plusieurs fonctions (voire toutes) d'un programme ont besoin du même ensemble de variables. Ce serait alors trop encombrant de passer toutes les variables comme paramètres d'une fonction à l'autre. En langage C/C++, nous pouvons allonger la durée de vie d'une variable locale en la déclarant static. Lors d'un nouvel appel à la fonction, la variable garde la valeur obtenue à la fin de l'exécution précédente. Une variable static est initialisée à 0 lors du premier appel à la fonction. Le programme suivant montre l effet de déclarer une variable comme static.

63 Chap. 5 : Les fonctions 59 #include <iostream> using namespace std; void fonc_static(); int globale; // variable globale void main(void){ int i; // variable locale for (i=0;i<5 ; i++) { globale--; fonc_static(); Programme 5.5 void fonc_static(){ static int i; // variable static cout <<"\n globale= " << globale << " et static : "<< i; i +=2; L exécution du programme affiche : globale= -1 et static : i=0 globale= -2 et static : i=2 globale= -3 et static : i=4 globale= -4 et static : i=6 globale= -5 et static : i= Récursivité Le langage C++ permet qu'une fonction s'appelle elle-même de manière récursive. Les exemples classiques sont la tour de Hanoï et le calcul de la factorielle d un nombre, qui peut être défini comme: int fact (int n ) { if ( n < 0) return 1; //code d'erreur else if ( n == 0 ) return 1; // 0! = 1 else return n*fact( n-1 ); // n! = n*(n-1)! Nous n'insisterons pas ici sur les avantages et inconvénients de la récursivité. Disons simplement, qu'en matière d'écriture de programme, la récursivité est un outil puissant et de grande souplesse, indispensable d'ailleurs dans le traitement de structures de données dynamiques Surcharge des fonctions La surcharge de fonction consiste à définir des fonctions ayant le même nom, mais un type et/ou un nombre d'arguments différents. Cette technique permet donc de définir des fonctions faisant ou non le même traitement dans des contextes différents. Par exemple on peut définir int Somme(int, int) et float Somme(float,float), deux fonctions de même nom ayant une implémentation différente suivant le type de données, c'est le compilateur qui détermine la fonction à appeler d après le nombre et le type des arguments d appel de la fonction. Cependant, on ne peut pas surcharger deux fonctions ayant exactement les mêmes types d'arguments mais retournant un type différent.

64 Chap. 5 : Les fonctions 60 #include <iostream> using namespace std; int Somme(int x, int y){ cout << "Dans la fonction int " <<(x+y) << endl; return (x+y); float Somme(float x, float y){ cout << "Dans la fonction float "<< (x+y) << endl; return (x+y); void Somme(const int x, const int y, const int z){ cout << "Dans la fonction void "<< (x+y+z) << endl; void main( ) { int i=2, j=3; float k=2.3, z=2.2; cout <<"Retour de la fonction int " << Somme(i,j) << endl; cout <<"Retour de la fonction float "<< Somme(k,z)<< endl; Somme(1,2,3); Programme 5.6 L exécution nous donne : Dans la fonction int 5 Retour de la fonction int 5 Dans la fonction float 4.5 Retour de la fonction float 4.5 Dans la fonction void Paramètres par défaut A chaque paramètre déclaré dans un prototype ou dans une définition d une fonction correspond une valeur que le programme doit lui passer. Les prototypes qui déclarent une valeur par défaut pour le paramètre font exception. Une valeur par défaut est une valeur utilisée lorsque aucune autre n'est fournie. Lorsqu'un paramètre est fréquemment appelé avec une valeur donnée, il serait intéressant de pouvoir l'omettre et simplifier ainsi l'appel à la fonction. C++ procure cette facilité en nous autorisant à fournir une valeur par défaut aux paramètres. Cette valeur doit être précisée dans la déclaration de la fonction. Elle ne doit pas apparaître en revanche lors de la définition. Une valeur par défaut est une valeur utilisée lorsque aucune autre n'est fournie. Les déclarations suivantes sont équivalentes : void fonct(int) ; void fonct(int x) ; void fonct(int x=5) ; void fonct(int =5) ; Le programme suivant illustre l effet des paramètres par défaut : #include <iostream> using namespace std; void affiche(int un = 1, int deux = 2, int trois = 3) { cout << un << ' ' << deux << ' ' << trois << '\n'; void main () { affiche(1, 2, 3); affiche(100, 200); affiche(1000); affiche(); Programme 5.7 Le résultat du programme 5.7 est le suivant :

65 Chap. 5 : Les fonctions 61 Pour fixer les idées sur le fonctionnement des paramètres par défaut dans les fonctions, voici un autre programme. #include <iostream> using namespace std; int Volume(int longueur, int largeur = 3, int hauteur = 1); void main(){ int longueur = 10; int largeur = 5; int hauteur = 2; int volume; volume = Volume(longueur, largeur, hauteur); cout << "Le premier volume est egal a : " << volume << "\n"; volume = Volume(longueur, largeur); cout << "Le deuxieme volume est egal a : " << volume << "\n"; volume = Volume(longueur); cout << "Le troisieme volume est egal a : " << volume << "\n"; Volume(int longueur, int largeur, int hauteur){ return (longueur * largeur * hauteur); Programme 5.8 Ce programme produit le résultat suivant : Le premier volume est egal a : 100 Le deuxieme volume est egal a : 50 Le troisieme volume est egal a : 30 Ce qu il faut au moins retenir : Un programme C++ ne doit pas nécessairement commencer par la fonction main(), et ce sera d ailleurs rarement le cas. La seule chose qui compte pour qu'un programme ait un point d'entrée et soit donc exécutable, est qu il y ait une fonction main() quelque part dans ce programme. return met fin à l exécution des instructions d une fonction et rend le contrôle à la appelante. fonction Une fonction ne peut pas modifier la valeur d une variable, locale à main() ou à une autre fonction, de type standard (int, char, ) passée en paramètre par valeur. Par contre, elle peut, si nous le désirons, modifier les éléments d'un tableau passé en paramètre, car c est un passage par adresse. Les tableaux peuvent être passés comme paramètres de fonctions. Ils ne peuvent cependant pas être retournés comme résultat d'une fonction (par le mot-clé return). Une variable globale est une variable connue de tout le programme, contrairement à une variable locale qui est connue uniquement dans la fonction où elle est déclarée. On n utilise des variables globales que lorsque c est nécessaire. En effet, c'est contraire à la lisibilité et à la modularité des programmes. Le langage C++ permet d utiliser la surcharge des fonctions. Ces dernières portent le même nom mais pas forcément le même nombre et/ou type des arguments. Le but est qu elles exécutent des opérations différentes.

66 Chap. 5 : Les fonctions 62 Exercices 5.1. Transformer l exercice 3.6. en utilisant une fonction dont le seul rôle est de calculer le PGCD de deux nombres passés comme paramètres de la fonction Transformer l exercice en utilisant une fonction " multiplication" Ecrire une fonction MIN et une fonction MAX qui déterminent le minimum et le maximum de deux nombres réels. Ecrire un programme se servant des fonctions MIN et MAX pour déterminer le minimum et le maximum de cinq nombres réels entrés au clavier Ecrire un programme qui calcule le produit scalaire de deux vecteurs d'entiers U et V de même dimension. Utiliser une fonction de saisie pour remplir les deux vecteurs. Exemple: ( ) * ( ) = 5*1 + 2*(-3) + (-4)*6 = Coder un programme qui range au maximum (taille Nmax ) 20 nombres entiers saisis au clavier dans un tableau. Il doit gérer en boucle le menu de choix suivant : A- Saisie et affichage B- Moyenne C- Suppression du Max et affichage D- Suppression du Min et affichage E- Ajout d un entier à une position donnée F- Supprimer les doublons Q- Quitter Le point A sera traité par deux fonctions : Saisie : la saisie au clavier des entiers et leur rangement dans le tableau. Dans cette fonction on demandera le nombre d éléments (NE<= Nmax) à saisir. Affichage : affichage des données. Le point B sera traité par une fonction : Moyenne : fonction de calcul de la moyenne du tableau (avec affichage du résultat). Le point C sera traité par trois fonctions : Max_elem : une fonction qui retourne la position du maximum des valeurs du tableau. Supprimer : supprime le Max du tableau. Affichage : affichage des données. Le point D sera traité par trois fonctions : Min_elem : une fonction qui retourne la position du minimum des valeurs du tableau. Supprimer : supprime le Min du tableau. Affichage : affichage des données. Le point E sera traité par deux fonctions : Ajout : c est une fonction où on demande à l utilisateur d introduire l entier et la position. Puis vous insérez l entier dans le tableau à la position indiquée. Affichage : affichage des données. Le point F sera traité par une fonction : Doublons : fonction qui supprime les doublons du tableau (avec affichage du résultat).

67 Chapitre 6: Les pointeurs et les références Les pointeurs sont des variables qui jouent un rôle primordial en C et en C++. Ils nous permettent d'écrire, avec une certaine discipline, des programmes clairs, compacts, efficients et fournissent souvent des solutions raisonnables à un problème. Cependant, il faut être très attentif en utilisant cet outil puissant, car les pointeurs ne doivent pas être employés négligemment. En effet, il est assez facile de créer des pointeurs qui pointent n'importe où et malheureusement parfois sur des zones mémoires utilisées par le système. Les références sont des identificateurs synonymes d'autres identificateurs, qui permettent de manipuler certaines notions introduites avec les pointeurs plus souplement. Elles n'existent qu'en C Un pointeur: qu'est-ce que c'est? La mémoire est découpée en octets. Chaque octet est repéré par son numéro d'ordre, ou adresse (emplacement en mémoire). Un pointeur pointe vers un octet en indiquant son adresse (une valeur). Ici, pointer signifie «faire référence à». En pratique, un pointeur est une variable qui contient une valeur de type adresse et pas la valeur d'un des types vus précédemment. C est donc une variable dont le contenu est l'adresse mémoire d'une autre variable (objet), c'est-àdire la position en mémoire de cette autre variable (objet). Un pointeur permet donc de retrouver la valeur d'une variable (par son adresse) et d'y accéder. On dit aussi que le pointeur renvoie ou pointe vers la variable concernée, cela via son contenu consistant en l adresse de cette variable. La variable (objet) pointée peut être référencée via le pointeur. Exemple 1 Pointeur p: valeur 5A0F3 (adresse hexadécimale de la case mémoire où se trouve la valeur de i) Adresse 5A0F3: valeur 35 (correspondant à la valeur d'un entier i) p i Noms des variables 5A0F3 60C A0F3 Valeurs des variables Adresses mémoires Mémoire Si un pointeur p contient l'adresse d'une variable i, on dit que 'p pointe sur i'. Remarque Les pointeurs et les noms de variables ont le même rôle: Ils donnent accès à un emplacement dans la mémoire interne de l'ordinateur. Il faut quand même bien faire la différence: un pointeur est une variable qui peut pointer sur différentes adresses ; le nom d'une variable reste toujours lié à la même adresse. Il faut signaler que l on parle parfois de pointeur dont la valeur est constante (adresse constante). Par exemple, les noms des tableaux sont des pointeurs constants équivalents à l adresse de la première composante du tableau concerné.

68 Chap. 6: Les pointeurs et les références Déclaration de pointeurs Les pointeurs se déclarent, comme les variables, en donnant le type de l'objet vers lequel ils devront pointer. Cependant, pour différencier une variable quelconque d une variable «pointeur», le type de base (char, float, int, ) est toujours suivi d une étoile *. Cela se fait par l'instruction: type* nom_du_pointeur; Exemple 2 : on peut déclarer les pointeurs suivants : int *p, *q, r ; // 2 pointeurs p et q vers des entiers et 1 entier r char *s; // 1 pointeur s vers un caractère float *pr; // 1 pointeur pr pointant sur un float int **tab; // 1 pointeur tab pointant sur un pointeur qui pointe sur un int L'opérateur * désigne en fait le contenu de l'adresse, c est l opérateur de déréférencement Valeurs pointées et adresses La manipulation des pointeurs nécessite une bonne maîtrise des deux opérateurs & et *. Lors de l utilisation des pointeurs, nous avons besoin : - d'un opérateur 'adresse de': & pour obtenir l'adresse d'une variable, - d'un opérateur 'contenu de': * pour accéder au contenu d'une adresse, - d'une syntaxe de déclaration pour pouvoir déclarer un pointeur. Pour fixer les idées, prenons l exemple 3: int i = 35; int *p; // déclaration : p est un pointeur pointant sur un entier p = &i; /* initialisation du pointeur p, affecte l'adresse de la variable i. p pointe maintenant vers la zone mémoire où est stockée la variable i*/ cout << *p; //affiche la valeur pointée par p, donc 35 p contient l adresse de la variable i (p = &i ) alors que *p contient le contenu de la variable, donc 35. On peut donc accéder à la valeur de la variable en passant par son adresse et en utilisant l opérateur contenu de *. Attention : int *p; *p = 100 ; // provoque une erreur à l exécution. Pourquoi? Remarque : Comme pour les autres variables, la valeur d une variable pointeur est indéfinie lors de la déclaration et le reste tant qu on ne lui affecte pas explicitement une valeur. Il est même possible de modifier les valeurs pointées comme le montre les instructions de l exemple 4.

69 Chap. 6: Les pointeurs et les références 65 Exemple 4 : int i = 35, j; int *p, *q; p = &i; // manipulation de i via p; p=&i = 0x0012ff7c *p = 35 j = *p; // j = 35 *p = 10; // *p=i=10 i= 20; // i=*p=20 (*p)++; //équivalent à i++, donc i=*p= 21. Notez l importance des parenthèses!!! q = p; // p et q pointent maintenant ensemble vers la même adresse 0x0012ff7c i=50 ; // i=*p=*q= 50 *(q+1)= 29; // on range 29, 4 cases mémoire plus loin *p=*q=i reste à 50 - p pointe sur i, - le contenu de i (référencé par *p) est affecté à j, et - le contenu de i (référencé par *p) est mis à 10, - le contenu de p est mis à 20, - le contenu de p est mis à 21, - le contenu de q est mis à p et q pointent vers la même adresse et leur contenu est égal à le contenu de p et de q est mis à le contenu de p et de q n est pas changé par *(q+1)= 29;. Les opérateurs * et & ont la même priorité que les autres opérateurs unaires (la négation!, l'incrémentation ++, la décrémentation --). Dans une même expression, les opérateurs unaires *, &,!, ++, -- sont évalués de droite à gauche. Nous conseillons au programmeur de faire attention lors de l utilisation des opérateurs unaires ++ et - -, notamment avec les pointeurs. Ainsi *p++ est différent de (*p)++. Si au lieu de : on avait écrit : i= 20; // i=*p=20 (*p)++; // est équivalent à i++, donc i=*p= 21 i= 20; // i=*p=20 *p++; // est équivalent à *p puis p++ : i=20 *p=? le nouveau p ne pointe pas vers i // mais bien sur la case mémoire située une adresse plus loin que i. Comme les opérateurs unaires * et ++ sont évalués de droite à gauche, sans les parenthèses, le pointeur p serait incrémenté, donc ne pointerait plus sur i, mais sur une valeur peut-être inconnue de l utilisateur.

70 Chap. 6: Les pointeurs et les références Une référence: qu'est-ce que c'est? Un type référence définit une variable dont la valeur est l adresse d une zone mémoire typée. Une référence vers un objet permet de définir un nouveau nom, un alias, un synonyme, pour désigner l emplacement mémoire de l objet référencé. En tant qu'alias, la référence doit impérativement être initialisée, avec l'objet référencé. Une fois initialisée pour référencer un objet donné, une référence ne peut plus être changée pour référencer un autre objet (variable), puisqu il s agit d un synonyme pour le premier. Une référence s exprime en préfixant le nom de la variable avec l opérateur «&» et toutes les occurrences de la référence sont implicitement déréférencées pour accéder à la variable référence. Déclaration de références Les références se déclarent de la manière suivante : type &nom_référence = identificateur; La référence doit être initialisée à la déclaration. Après cette déclaration, nom_référence peut être utilisé partout où identificateur peut l'être. Ce sont des synonymes. Exemple5 : int i = 35, j; int &ref = i ; int &ErRef; /* ref une référence sur la variable i. permet au programme de manipuler i sous un autre nom que celui de sa déclaration. i et ref deux identificateurs qui représentent la même variable */ // INTERDIT : une référence doit être initialisée j = ref; // j = la valeur de l'objet référencé par ref (j = i = 35) ref = 100 ; // ref=i= 100 ; j reste à 35 i= j ; // ref=i=j = Pointeurs, références et arguments de fonctions En C, les pointeurs sont fort utiles lors du passage de paramètres modifiables dans des fonctions. Ceci a pour conséquence de produire un code peu lisible et constitue une source fréquente d'erreurs, surtout pour les personnes peu habituées à cette gymnastique. Le langage C++ pallie à cette lacune en introduisant le passage de paramètres par références. Rappelons ici que le passage des paramètres par valeur implique qu'à l'entrée de la fonction, une copie de la valeur de ces paramètres est réalisée. La fonction travaille elle-même sur cette copie, et donc, en aucun cas, ne modifie la valeur originale. Nous avons vu que si nous voulons sortir les modifications d une variable vers la fonction appelante, l instruction return est à notre disposition. Mais dans le cas où il s agit de retourner plusieurs variables, il faut trouver une autre solution.

71 Chap. 6: Les pointeurs et les références 67 Afin d illustrer l effet et le fonctionnement des pointeurs et des références, nous reprenons l exemple du Programme 5.3. #include <iostream> using namespace std; void affiche (int a, int b) { cout<<"\t Valeurs i = " << a << " j = " << b << endl; void echange (int, int); void main () { int i= 1, j=2; affiche (i, j); echange (i, j); affiche (i, j); void echange (int*, int*); void main () { int i= 1, j=2; affiche (i, j); echange (&i, &j); affiche (i, j); void echange (int&, int&); void main () { int i= 1, j=2; affiche (i, j); echange (i, j); affiche (i, j); void echange (int a, int b) { int tmp; tmp = b; b = a; a = tmp; void echange (int *a, int *b) { int tmp; tmp = *b; *b = *a; *a = tmp; void echange (int &a, int &b) { int tmp; tmp = b; b = a; a = tmp; Résultats : Valeurs i = 1 j = 2 Valeurs i = 1 j = 2 Valeurs i = 1 j = 2 Valeurs i = 2 j = 1 Programme 6.1 Valeurs i = 1 j = 2 Valeurs i = 2 j = Partie commune aux trois programmes Passage des paramètres par valeur Passage des paramètres par référence de pointeur Passage des paramètres par référence 2 En la fonction echange est syntaxiquement correcte pour intervertir les valeurs des variables entières a et b. Malheureusement, codée comme telle, elle n'aura aucun effet! En effet, ce sont des copies (en variables temporaires locales) des variables a et b qui seront interverties, mais pas les originaux! Utiliser l instruction return peut éventuellement nous sortir une valeur, mais pas les deux. Contrairement au passage par valeur, le passage par référence ou par adresse, n'effectue pas de copie du paramètre: il passe une référence sur celui-ci. En conséquence, une fonction passant des paramètres par référence ne pourra jamais prendre (en paramètre) une constante, mais uniquement une variable. Ce mode de passage peut donc être intéressant, surtout si un paramètre est important

72 Chap. 6: Les pointeurs et les références 68 en terme de taille (un tableau, une structure,...). C est le mode qu il faut utiliser si nous voulons modifier les paramètres d une fonction. Ceci se fait de manière explicite, en utilisant soit les pointeurs soit les références. Les références et les pointeurs sont étroitement liés. Utiliser une référence pour manipuler un objet revient exactement au même que de manipuler un pointeur contenant l'adresse de cet objet. Les références permettent simplement d'obtenir le même résultat que les pointeurs, mais avec une plus grande facilité d'écriture. En effet, comme le montre le programme, le code est nettement plus clair. Il est aussi beaucoup plus sûr puisqu'on ne doit plus référencer à l'appel (&a) ni déréférencer dans la fonction (*a). Le risque d'erreur dans la conception et l'utilisation des fonctions est donc singulièrement réduit. C est pour ces raisons que nous préférons plutôt utiliser les références que les pointeurs. Ce sera le cas dans ce syllabus lors du passage des paramètres par références. Nous attirons l attention sur la manière d écrire l en-tête de la définition et de l appel de la fonction : Définition : void echange (int &pa, int &pb) Appel : echange ( x, y); Programme 6.2 : Cet exemple a été traité auparavant dans le chapitre consacré aux fonctions (Programme 5.2). Maintenant que nous connaissons les références, ce programme devient : #include <iostream> using namespace std; void Modifier(int &v); void main(){ int v = 5; Modifier(v); cout << "\n main: v = " << v; // Variable locale à main() // Appel de la fonction Modifier /* Affiche la valeur de v après passage dans la fonction Modifier*/ void Modifier(int &v){ v = v * 100; cout << " Modifier: v = "<< v << " son adresse &v = " << &v ; Programme 6.2 L exécution de ce programme donne le résultat suivant : Modifier: v = 500 son adresse &v = 0x0012FF7C main: v = 500 Donc la modification effectuée par la fonction Modifier est transmise à la fonction main(). Un autre exemple illustrant la différence entre le passage des paramètres par valeur et par référence est présenté dans le programme 6.3.

73 Chap. 6: Les pointeurs et les références 69 #include <iostream> using namespace std; void affiche(int i, float r, char c){ cout<< "\n int = " << i << " float = " << r << " char = " << c ; void Saisie(int &i, float r, char &cc){ cout << "\n Donner un entier : "; cin >> i; // 12 cout << " Donner un reel : "; cin >> r; // cout << " Donner un caractere : "; cin >> cc; // Z void main(){ int N=5; float f=6.7; char C = 'A'; Programme 6.3 affiche(n, f, C); Saisie(N, f, C); affiche(n, f, C); Le résultat de ce programme est : int = 5 float = 6.7 char = A Donner un entier : 12 Donner un reel : Donner un caractere : Z int = 12 float = 6.7 char = Z 6.4. Pointeurs et tableaux Il existe une relation très étroite entre les tableaux et les pointeurs. Cela est dû au fait que le nom d un tableau représente un pointeur sur le premier élément du tableau. Comme les tableaux sont stockés de manière contiguë en mémoire, chaque opération avec des indices de tableaux peut aussi être exprimée à l'aide de pointeurs. Ainsi, accéder à la composante suivante du tableau peut s effectuer en passant à l'adresse suivante. Rappelons également que, comme paramètre de fonction, un tableau est en fait passé par l'adresse de sa première composante. Il est donc modifiable, car passé implicitement par adresse. Afin de pouvoir utiliser l'arithmétique des pointeurs pour manipuler les éléments des tableaux, le C++ effectue les conversions implicites suivantes lorsque nécessaire : tableau vers pointeur d'élément ; pointeur d'élément vers tableau.

74 Chap. 6: Les pointeurs et les références 70 Cela permet de considérer les expressions suivantes comme équivalentes : int T[N]; int i; T[i] est équivalent à *(T + i). T est une constante représentant l adresse de l élément T[0] (T=&T[0]). L expression *T désigne T[0]. L accès à un élément du tableau peut se faire non seulement par le nom du tableau accompagné d un indice, mais aussi par un pointeur manipulé par des opérations spécifiques de pointeurs. Si le pointeur p repère l'élément d'indice i du tableau T, p + j (de même p-j) est une valeur de type pointeur qui repère l'élément d'indice i + j (i j) du tableau T (en supposant qu'ils existent). Si on a : const int N = 100; int T[N]; int * p ; p = &T[0]; // dim du tableau // p repère le premier élément de T Dans l instruction ci-dessus, remarquez que nous rangeons dans p l adresse du premier élément du tableau. Il aurait été incorrect d écrire p = &T ; car T est un nom du tableau et est vu par le compilateur comme une constante ; alors que l opérateur & s applique à une variable pour en fournir l adresse. En revanche, nous aurions pu écrire : p=t ; L'expression p + N est valide, mais p - 1 et p + N + 1 ne le sont pas. Après les déclarations nous pouvons écrire int T[10], *p; p = &T[4]; et utiliser l'opérateur d'indexation sur p, p[0] étant T[4], p[1] étant T [5], etc. p peut donc être utilisé comme un sous-tableau de T. Exemple 6 : manipulation de pointeurs : const int N = 100; // dim du tableau int T[N]; int *p,*q,*r,*s; p = &T[0]; /* p repère le premier élément de T équivalent à p=t */ q = p + (N-1); // q repère le dernier élément de T r = &T[N-1]; s = r - (N-1); // r repère le dernier élément de T // s repère le premier élément de T

75 Chap. 6: Les pointeurs et les références 71 #include <iostream> using namespace std; Programme 6.4 void main(){ int T[6] = { 2, 6, 4, 5, 10, 8 ; int *p; p = T; // p repère le premier élément de T cout<< *p << endl ; // affiche 2 p++; cout<< *p << endl ; // affiche 6 p += 4; cout<< *p << endl ; // affiche 8 Ce programme peut être représentée par le graphique suivant : p++ p+=4 p 1000 T Adresse mémoire #include <iostream> using namespace std; void main(){ const int N=6 ; int T[N] = { 2, 4, 6, 8, 10, 12 ; int *p, i; cout<< "T = " << T << " &T[0] = " << &T[0] << endl; p =T; cout<< "for1...\n"; for (i=0; i<n ; i++){ cout<< "p+" << i << " = " << p+i << "\tp["<<i<<"]= " << p[i] << "\t *(p+"<<i<<") = " << *(p+i)<< endl; cout<< "END for1...\n"; Programme 6.5 *p++ = 15; cout<< "for2...\n"; for (i=0; i<n ; i++){ cout<< "T["<<i<<"]="<<T[i]<<"\t p+"<<i<<" = " <<p+i << " p[" << i<<"]=" << p[i] << "\t *(p+"<<i<<") = " << *(p+i)<< endl; cout<< "END for2...\n";

76 Chap. 6: Les pointeurs et les références 72 L exécution de ce programme donne le résultat suivant : T = 0x0012FF68 &T[0] = 0x0012FF68 for1... p+0 = 0x0012FF68 p[0]= 2 *(p+0) = 2 p+1 = 0x0012FF6C p[1]= 4 *(p+1) = 4 p+2 = 0x0012FF70 p[2]= 6 *(p+2) = 6 p+3 = 0x0012FF74 p[3]= 8 *(p+3) = 8 p+4 = 0x0012FF78 p[4]= 10 *(p+4) = 10 p+5 = 0x0012FF7C p[5]= 12 *(p+5) = 12 END for1... for2... T[0]=15 p+0 = 0x0012FF6C p[0]=4 *(p+0) = 4 T[1]=4 p+1 = 0x0012FF70 p[1]=6 *(p+1) = 6 T[2]=6 p+2 = 0x0012FF74 p[2]=8 *(p+2) = 8 T[3]=8 p+3 = 0x0012FF78 p[3]=10 *(p+3) = 10 T[4]=10 p+4 = 0x0012FF7C p[4]=12 *(p+4) = 12 T[5]=12 p+5 = 0x0012FF80 p[5]= *(p+5) = END for Allocation dynamique de la mémoire Nous avons vu que l'utilisation de tableaux nous force à réserver plus de places en mémoire que nécessaire. Si nous générons ces données, dont nous ne pouvons pas prévoir le nombre et la taille lors de la programmation, il nous faut, en plus de l utilisation des pointeurs, des moyens pour réserver et libérer de la mémoire en fonction de nos besoins. Nous parlons alors de l'allocation dynamique de la mémoire. Pour cette gestion dynamique de la mémoire, le langage C++ fournit des moyens pour allouer et restituer la mémoire. Pour cela, il dispose d'opérateurs spécifiques : new, delete, new[] et delete[]. La syntaxe de ces opérateurs est respectivement la suivante : new type delete pointeur new type[taille] delete[] pointeur L opérateur new permet d'allouer de la mémoire, alors que l opérateur delete la restitue. La syntaxe de new est très simple, il suffit de faire suivre le mot clé new du type de la variable à allouer, et l'opérateur renvoie directement un pointeur sur cette variable avec le bon type. Par exemple, l'allocation d'un entier se fait comme suit : int *pi = new int; La syntaxe de delete est encore plus simple, puisqu'il suffit de faire suivre le mot clé delete du pointeur sur la zone mémoire à libérer : delete pi; Les opérateurs new[] et delete[] sont utilisés pour allouer et restituer la mémoire pour les types tableaux. L'emploi de l'opérateur new[] nécessite de donner la taille du tableau à allouer. Ainsi, on pourra créer un tableau de 1000 entiers de la manière suivante : int *Tableau=new int[1000]; et détruire ce tableau de la manière suivante : delete[] Tableau;

77 Chap. 6: Les pointeurs et les références 73 Le programme suivant nous donne un aperçu sur la manière d allouer et de libérer la mémoire: #include <iostream> using namespace std; void affiche(int T[], int d, char C[]){ for(int i=0; i<d; i++) cout<< "\n T["<<i<<"] = " << T[i] << " C["<<i<<"] = " <<C[i]; cout << endl; void main(){ int N=6, *T, i; char *C = new char[n]; T= new int[n]; affiche(t, N, C); for(i=0; i<n; i++){ T[i]=i; C[i]='A'+i; affiche(t, N, C); delete[] T; affiche(t, N, C); delete[] C; affiche(t, N, C); Programme 6.6 Ce programme produit le résultat suivant : T[0] = C[0] = T[1] = C[1] = T[2] = C[2] = T[3] = C[3] = T[4] = C[4] = T[5] = C[5] = T[0] = 0 C[0] = A T[1] = 1 C[1] = B T[2] = 2 C[2] = C T[3] = 3 C[3] = D T[4] = 4 C[4] = E T[5] = 5 C[5] = F T[0] = C[0] = A T[1] = C[1] = B T[2] = C[2] = C T[3] = C[3] = D T[4] = C[4] = E T[5] = C[5] = F T[0] = C[0] = T[1] = C[1] = T[2] = C[2] = T[3] = C[3] = T[4] = C[4] = T[5] = C[5] = Ce qu il faut au moins retenir : Quand une fonction1 appelle une autre fonction2 et que la première a besoin des modifications des variables passées en paramètres de la seconde, il faut passer les paramètres par référence. Ceci se fait de manière explicite, en utilisant les &. Quand le paramètre de la fonction est une référence, la déclaration et l appel de la fonction, en comparaison à un paramètre traditionnel, se font comme suit : déclaration : func(int x) func(int &x) appel : func( y) func(y) Attention aux erreurs suivantes : int i = 35; int &p; p = &i; //Erreur //Erreur int i = 35; int *p; *p = i; //Erreur int i = 35; int &p= i;. int i = 35; int *p; p = &i; (*p)++ est différent de *p++ // OK Pour réserver de la mémoire à un pointeur, on utilise l opérateur new. Dans un programme, il est fort souhaitable d'avoir autant d opérateurs delete que d opérateurs new. //OK

78 Chap. 6: Les pointeurs et les références 74 Exercices 6.1. Les opérations d affectation suivantes sont-elles correctes? int a, *p ; a. a=*p ; b. *p=&a; c. *p=*(&a); d. a=p; e. p=&a; f. a=(int)p; 6.2. Qu affiche le programme suivant? Pourquoi? #include <iostream> using namespace std; void main(){ int *p, x, y; int &r=x; p = &x; x = 10; y = *p - 1; cout <<"\t x= "<<x<< ";\t *p = "<< *p << ";\t r= "<< r << ";\t y=*p-1="<<y << endl; *p += 1; cout <<" *p += 1 ==>\n\t x= "<<x<< ";\t *p = "<< *p << ";\t r= "<< r << ";\t y= "<<y << endl; (*p)++; cout <<" (*p)++ ==>\n\t x= "<<x<< ";\t *p = "<< *p << ";\t r= "<< r << ";\t y= "<<y << endl; r++; cout <<" r++ ==>\n\t x= "<<x<< ";\t *p = "<< *p << ";\t r= "<< r << ";\t y= "<<y << endl; *p++; cout <<" *p++ ==>\n\t x= "<<x<< ";\t *p = "<< *p << ";\t r= "<< r << ";\t y= "<<y << endl; 6.3. Que faut-il ajouter à ce programme pour qu il puisse fonctionner correctement? void main() { int *p ; *p = 10; cout << " *p = " << *p ; 6.4. Transformer l exercice 5.3. en remplaçant les fonctions MIN et MAX par une seule fonction MIN_MAX qui détermine le minimum et le maximum d un vecteur de nombres réels entrés au clavier. Ces deux valeurs doivent être transmises au main Ecrire la fonction Affiche et la fonction Crypt de cryptage d'un caractère pour que le programme suivant puisse : décaler chaque lettre de Tab de 5, ainsi un a sera remplacé par un f, un b par un g, etc. On ne cryptera que les lettres majuscules et minuscules sans toucher ni à la ponctuation ni à la mise en page. On supposera que les codes des lettres se suivent de a à z et de A à Z. void main() { char *p, Tab[80]; cout <<"\n Une phrase...: "<< endl; cin >> Tab; p=tab; while(*p) Crypt(p++); cout << "\nresultat :"; Affiche(Tab,??); Exemple : Les sanglots longs des violons de l'automne Deviendra : Qjx xfslqtyx qtslx ijx antqtsx ij q'fzytrsj...

79 Chapitre 7: Les fichiers 7.1. Généralité Il est parfois agréable de pouvoir traiter d autres données que celles fournies à l aide du clavier pendant l exécution du programme, surtout quand leur nombre est élevé. Il arrive aussi que l'on veuille sauvegarder des données ou des résultats obtenus sous une forme un peu plus permanente qu un simple affichage à l écran, ce qui permet de les réexploiter lors d'une prochaine exécution. Ces problèmes peuvent être résolus en utilisant des fichiers. Un fichier est un ensemble structuré d'informations stockées sur un support externe (disque dur, disquette, CD-ROM, DVD, ). Ecrire ou lire sur une mémoire de masse des données non volatiles, qui restent utilisables après l'exécution d'un programme, est évidemment fondamental. Nous allons voir dans ce chapitre, comment nous pouvons manipuler des fichiers : les déclarer, les créer, les ouvrir, lire ou écrire voire modifier des données s y trouvant et les fermer. Un fichier est une suite d'octets. Les informations contenues dans le fichier ne sont pas forcément de même type (un char, un int, une structure...) Un pointeur fournit l'adresse d'une information quelconque. pointeur Dans des fichiers séquentiels, les enregistrements sont mémorisés consécutivement dans l'ordre de leur entrée et peuvent seulement être lus dans cet ordre. Si on a besoin d'un enregistrement précis dans un fichier séquentiel, il faut lire tous les enregistrements qui le précèdent en se déplaçant (via un pointeur) depuis le premier Accès aux fichiers Pour pouvoir manipuler un fichier de données en C++, il faut tout d'abord inclure dans le fichier.cpp la librairie fstream qui fournit les fonctionnalités de manipulation de fichiers. #include <fstream> On y trouve essentiellement : la classe ofstream (output file stream) qui permet d écrire les données dans le fichier ; la classe ifstream (input file stream) qui permet de lire les données du fichier ; la classe fstream (file stream) dérivant les fichiers en lecture/écriture. Ces classes sont pourvues de fonctions membre qui vont nous permettre d opérer sur les fichiers.

80 Chap. 7: Les fichiers Ouverture d un fichier La première chose à faire, quand on manipule un fichier, est de l'ouvrir. Pour ce faire, on déclare une variable en lui associant le nom physique du fichier visé. Cette variable est de type ofstream s il s agit d écriture, de type ifstream s il s agit de lecture ou de type fstream s il s agit de lecture/écriture. La méthode la plus simple pour ouvrir un fichier est d initialiser la variable qui doit lui être associée à l aide d une chaîne de caractères décrivant le chemin d accès au fichier. ifstream input("data.txt"); ofstream output("res.txt"); "Data.txt" et "Res.txt" sont des chaînes de caractères donnant les noms réels des fichiers physiques. Cependant, si les fichiers ne sont pas dans le même répertoire que le programme, il faut indiquer le chemin d'accès. Le caractère '\' s'écrit en C++ '\\', ce qui pourrait donc donner par exemple: ifstream input("c:\\labojeudi\\data.txt"); ofstream output("c:\\labojeudi\\res.txt"); Cette façon d ouvrir les fichiers présente plusieurs caractéristiques notables : Si le chemin d accès comporte un répertoire qui n existe pas, l ouverture échoue. Si le chemin est correct, mais que le fichier n existe pas, il est créé. Si le fichier existe, il est ouvert. S il s agit d ouverture en mode écriture, le contenu antérieur du fichier est perdu. Il faut noter qu il est possible de spécifier le mode d ouverture. Si par exemple, on désire une ouverture d un fichier existant sans perdre le contenu antérieur, on peut utiliser : ofstream output("c:\\labojeudi\\res.txt", ios::app); ios (input-output stream) est une classe de base fournie par le langage C++. Elle définit les opérations fondamentales d entrée/sortie. La constante ios::app (append) signifie que si le fichier existe, son contenu est conservé et toutes les données insérées seront ajoutées en fin de fichier. Remarques : Fichier dit «texte», les informations sont codées en ASCII. Ces fichiers sont lisibles par un éditeur de texte. Le dernier octet de ces fichiers est EOF (End Of File, caractère ASCII spécifique). Nous n'allons dans ce chapitre, qu'évoquer les fichiers textes à accès séquentiel. Il existe, bien sûr, d'autres fonctions pour travailler sur des fichiers binaires ou à accès direct. Nous renvoyons les lecteurs intéressés aux nombreux ouvrages référencés au début de ce syllabus.

81 Chap. 7: Les fichiers 77 La fonction open() Si l initialisation d une variable est une opération particulièrement simple, son inconvénient et qu elle ne peut avoir lieu qu une seule fois. Il arrive pourtant qu une même variable intervienne dans plusieurs ouvertures (ou tentatives d ouvertures ) successives. Les classes ofstream et ifstream proposent, pour répondre à ce besoin, une fonction membre nommée open() qui peut accepter comme paramètre un chemin d accès, comme le montre l exemple suivant: Ecriture : ofstream output; output.open("res.txt"); ofstream output; output.open("res.txt", ios::app); fstream output; output.open("res.txt", ios::out); Lecture : ifstream input ; input.open("data.txt"); fstream input; intput.open("res.txt", ios::in); ios::out et ios::in indiquent respectivement le mode d ouverture du fichier en écriture ou en lecture. L ouverture du fichier est une opération dont le succès ne peut être garanti. Il faut donc tester si l ouverture a réussi avant d effectuer des opérations sur les données du fichier. On détecte l échec d une ouverture de fichier en testant la valeur de la variable que l on vient de tenter d associer au fichier. Ceci est illustré dans les deux exemples suivants: ofstream output; output.open("res.txt"); if(!output) { cout<<"erreur d ouverture du fichier"<<endl; else{ cout<<"le fichier est bien ouvert"<<endl; ; ofstream output; string nom_fichier ; do{ cout << "\nnom du fichier : " ; cin >> nom_fichier ; output.open(nom_fichier ); while(!output) ;!output : indique si l opération sur le fichier a réussi Fermeture d un fichier Après l ouverture d un fichier et les différents traitements qui s y rapportent, lorsque vous avez donc fini d utiliser ce fichier, vos programmes doivent fermer ce flux en utilisant la fonction membre close() comme suit : output.close() ; input.close() ; On peut dire qu'entre les événements open() et close() le fichier est ouvert. Il est important de fermer les fichiers après les avoir utilisés, car seulement un nombre limité de fichiers peuvent être ouverts simultanément par un programme. De plus, le traitement désiré (lecture ou écriture) peut être différé à la fermeture du fichier. Sans fermeture de fichier, il

82 Chap. 7: Les fichiers 78 n'est, par exemple, pas certain que les toutes données que l'on voulait écrire aient été réellement transférées vers le support externe Lecture et écriture Il y a lieu maintenant de lire ou d écrire des informations dans les fichiers. Pour être précis, il importe de signaler que les données lues ou écrites le sont d'abord dans un tampon (buffer) de la mémoire, avant d'atteindre leur destination souhaitée. Ce tampon de fichier est une zone de mémoire RAM dans laquelle on range temporairement, avant leur transfert à destination, une certaine quantité de données lues ou écrites dans un fichier. L avantage est qu ainsi on n a pas besoin de déclencher une opération d entrée-sortie spécifique pour chaque donnée lue ou écrite. La gestion du tampon est à la charge du système qui intervient lorsque le tampon est plein ou lorsqu'on lui impose de vider le tampon, notamment avec la fonction membre close() L'ouverture ne donnant qu'un moyen d'accès, la lecture et/ou l écriture dans des fichiers se fait respectivement en utilisant les opérateurs >> et/ou <<. Mieux qu un long discours, nous donnons dans la suite des exemples que nous commentons au fur et a mesure. #include <fstream> using namespace std; void main() { ofstream ouput; // pour accès à la classe ofstream // on déclare une instance de la classe ofstream ouput.open("fichier.txt"); // on ouvre le fichier fichier.txt if(ouput) { // if (output!= NULL) on vérifie si l'ouverture se passe bien // ou if (! output.fail() ) pas d erreur cout<<"pas d Erreur"<<endl; char caract = 'A'; ouput << caract <<endl; int Entier = 10; ouput << Entier <<endl; float Reel = 3.14; ouput << Reel <<endl; double mondouble = ; ouput << mondouble <<endl; ouput.close(); else{ // si échec à l'ouverture cout<<"erreur"<<endl; // on ferme le fichier Programme 7.1. Les données dans le fichier "fichier.txt" sont : A

83 Chap. 7: Les fichiers 79 #include <fstream> using namespace std; void main() { ifstream input; input.open("fichier.txt"); // pour accès à la classe ifstream // on déclare une instance de la classe ifstream // on ouvre le fichier fichier.txt if(input) { // on vérifie si l'ouverture se passe bien cout<<"pas d Erreur"<<endl; char caract; input >> caract ; int Entier ; input >> Entier; float Reel ; input >> Reel ; double mondouble ; input >> mondouble ; input.close(); // on ferme le fichier cout << "Car = " << caract << " Entier = " << Entier << " Reel = " << Reel <<" Double = " << mondouble << endl; else{ // si échec à l'ouverture cout<<"erreur"<<endl; Programme 7.2. Ce programme affiche à l écran les informations suivantes : Pas -- Erreur Car = A Entier = 10 Reel = 3.14 Double = Il faut remarquer que l opérateur d extraction >> reconnaît les passages à la ligne. Si, par exemple, dans le Programme 7.1. la sauvegarde des données se fait sur une seule ligne, comme le montre cette instruction : ouput << caract <<' '<< Entier <<' '<< Reel <<' '<< mondouble <<endl; alors les données ne sont séparées que par un espace et non par un retour à la ligne. Le fichier "fichier.txt" aura l allure suivante : A Ce changement sur le Programme 7.1. n a pas d effet sur le Programme 7.2. qui reste valide. En effet, l espace constitue un séparateur de données pour l opérateur d extraction au même titre que le passage à la ligne. Cela a cependant des conséquences dans le cas d une extraction d une chaîne de caractères contenant des espaces. En effet, supposons que l on désire enregistrer un message comme ceci : ouput << "Bonjour : Debut du fichier..."<<endl;

84 Chap. 7: Les fichiers 80 son extraction se fait naturellement avec : char TXT[50] ; input >> TXT ; Malheureusement TXT ne contiendra que le mot "Bonjour" car après, l opérateur rencontre le séparateur espace. Il est évidemment, dans ce cas, possible d extraire le texte mot par mot, mais cela n est guère pratique. La classe ifstream possède une fonction membre qui permet de contourner cette difficulté. Il s agit de la fonction getline(). Donc, pour extraire toute la ligne, on utilisera : char TXT[50] ; // un tableau input.getline(txt,40); // extraire 40 caractères, au max, que l on transfert dans TXT cout << TXT; // affiche TXT : Bonjour : Debut du fichier... Question : Si la déclaration char TXT[50] est remplacée par string TXT que deviendra la suite des instructions? Supposons maintenant que le fichier que l on désire lire soit le suivant : Les donnees sont : On suppose que tout ce que l on a comme information sur ce fichier, est: un titre sur une ligne, des données de type entier dont le nombre est inconnu. Le programme suivant permet de lire ce fichier. #include <fstream> using namespace std; void main() { ifstream input; input.open("fichier.txt"); if(input) { char buffer[100] ; input.getline(buffer,100); cout << buffer << endl; while(!input.eof()){ int i; input >> i; cout << i << " ; "; input.close(); // end if else{ cout<<"erreur"<<endl; Programme 7.3.

85 Chap. 7: Les fichiers 81 L exécution de ce code affiche : Les donnees sont : 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 10 ; 11 ; 12 ; 13 ; 14 ; 15 ; La fin du fichier ( End Of File) est donnée par la méthode eof(). L instruction while(!input.eof()){ signifie : tant que la fin du fichier input n est pas atteinte, exécuter les instructions entre {. Le pointeur sur les données se déplace à chaque input >> i;. Pour ceux qui ne sont pas convaincus, il leur suffit de masquer cette dernière instruction et d'exécuter le programme afin de constater. Pour finir, on se propose de créer un fichier, nommé par l utilisateur, qui stocke des noms. L'utilisateur est invité à introduire au clavier le nom du fichier pour sauvegarder les données ainsi qu un certain nombre de noms. Le programme arrête l acquisition une fois que le nom introduit est FIN, puis se chargera de créer le fichier correspondant. Après avoir écrit et fermé le fichier, le Programme 7.4. va réouvrir le même fichier en lecture et afficher son contenu. #include <iostream> #include <string> #include <fstream> using namespace std; int main() { ifstream Lect; ofstream Ecri; string Nom; char NOM_FICHIER[30]; int i=0; // Première partie: Créer et remplir le fichier cout << "Entrez le nom du fichier a creer : " ; cin >> NOM_FICHIER; Ecri.open(NOM_FICHIER); Programme 7.4. if(ecri) { cout << "Entrez le Nom No " << i+1 << " : "; cin >> Nom; while ( Nom!= "FIN") { if (i!=0) Ecri << endl; i++; Ecri << Nom ; cout << "Entrez le Nom No " << i+1 << " : "; cin >> Nom; // while Ecri.close(); else{ cout << " Probleme d'ouverture de fichier Ecri " << endl; return 0; // Deuxième partie: Lire et afficher le contenu du fichier Lect.open(NOM_FICHIER);

86 Chap. 7: Les fichiers 82 if (Lect){ cout << "\n" << NOM_FICHIER << endl; i=0; while (!Lect.eof()) { Lect >> Nom; cout << "Nom " << i+1 << " : " << Nom << endl; i++; Lect.close(); else{ cout << " Probleme d'ouverture de fichier Lect " << endl; return 0; return 1; Dans ce programme, par souci de clarté, nous utilisons deux descripteurs (Lect, Ecri) au lieu d un seul. L exécution de ce programme, avec interaction de l utilisateur, nous donne : Entrez le nom du fichier a creer : Tintin_et_Compagnie.dat Entrez le Nom No 1 : Tintin Entrez le Nom No 2 : Milou Entrez le Nom No 3 : Haddock Entrez le Nom No 4 : Tournesol Entrez le Nom No 5 : FIN Tintin_et_Compagnie.dat Nom 1 : Tintin Nom 2 : Milou Nom 3 : Haddock Nom 4 : Tournesol Le programme effectue évidemment ce que l on demande. Cependant, si on introduit un nom contenant un espace, par exemple Bianca Castafiore, voilà comment se passe l exécution : Entrez le nom du fichier a creer : Tintin_et_Compagnie.dat Entrez le Nom No 1 : Tintin Entrez le Nom No 2 : Bianca Castafiore Entrez le Nom No 3 : Entrez la Nom No 4 : Milou Entrez le Nom No 5 : Haddock Entrez le Nom No 6 : FIN Tintin_et_Compagnie.dat Nom 1 : Tintin Nom 2 : Bianca Nom 3 : Castafiore Nom 4 : Milou Nom 5 : Haddock Après l introduction du nom Bianca Castafiore, le programme nous demande en même temps le nom N 3 et N 4. Il ne laisse pas la possibilité à l utilisateur d introduire le N 3. A l affichage du fichier, on remarque que Bianca a été stocké dans Nom 3 alors que Castafiore a été stocké dans Nom 4. On peut conclure que lorsqu on est en présence de chaînes de caractères contenant des

87 Chap. 7: Les fichiers 83 espaces, le programme ne fonctionne plus convenablement. La correction est demandée au lecteur sous forme d un exercice. Ce qu il faut au moins retenir : Un programme qui utilise des fichiers de données doit inclure fstream Pour écrire dans un fichier, on déclare une variable de type ofstream ofstream ouput; ouput.open("fichier.txt"); // on ouvre le fichier fichier.txt if(ouput) { // on teste si l'ouverture s est bien passée On utilise l opérateur d insertion << pour envoyer dans le fichier les données. Pour lire un fichier, on déclare une variable de type ifstraem ifstream input; input.open("fichier.txt"); // on ouvre le fichier fichier.txt if(input) { // on teste si l'ouverture s est bien passée On utilise l opérateur d extraction >> pour envoyer dans des variables les informations extraites du fichier. Pour extraire toute la ligne ou un ensemble de caractères on utilisera le fonction getline(). Utiliser la fonction close() pour fermer le fichier. input.close() ; Exercices 7.1. Copier un fichier texte dans un autre: créer un fichier "Essai.dat" sous éditeur par exemple. Tester le programme en vérifiant, après exécution, la présence du fichier copié à l endroit où il a été créé Modifier le programme 7.4 pour que le programme accepte des noms contenant des espaces Coder un programme qui enregistre et lit les informations suivantes : Les infos sont : Ecrire un programme interactif qui gère en boucle le menu suivant : 1 : Saisie 2 : Ajout Saisie est constituée d une fonction qui crée un fichier contenant, sur chaque ligne, des informations introduites par l utilisateur sur un ensemble d étudiants à savoir : le nom, le prénom et sa date de naissance. Ajout est une fonction qui a pour rôle d ajouter un nouvel étudiant dans le même fichier.

88 Chapitre 8: Les structures 8.1. Principes fondamentaux des structures Une structure est un ensemble de variables (de types éventuellement différents), définissant un nouveau type sous un seul nom, adapté à une gestion spécifique et à une manipulation facile des données. Elles sont fondamentales pour une programmation lisible, car il est rare qu'une application se contente de travailler avec les types de base. Plutôt que de travailler uniquement avec des caractères, des entiers ou des réels, on aura bien souvent besoin d'exprimer des classes d'objets comme des étudiants (possédant un nom, un prénom, une date de naissance, une adresse, , ), des comptes en banque (possédant un numéro, un titulaire, un solde, ), etc. Une structure se définit par un identificateur suivant le mot-clé struct, ainsi que par une liste de champs ou membres définis par un identificateur d'un type donné. Par exemple, pour gérer les coordonnées d'un point (abscisse et ordonnée) ou des clients, on pourra définir les types suivants : struct point { int x; int y; ; struct Client { string nom; char Code; ; Ces structures peuvent être représentées logiquement par les schémas suivants: point Client x y nom Code Une écriture comme struct {... s'appelle un constructeur de type. L identificateur point (Client) n est pas une variable, mais le nom de la structure et il va jouer un rôle d un nouveau type crée par l utilisateur pour déclarer des instances/objets de cette structure. Entre les accolades { et on trouve les déclarations des différents champs (ou membres ou attributs) de la structure. Les membres x et y pour la structure point et nom et Code pour la structure Client sont des variables. Le point-virgule, après l'accolade fermante de la déclaration de la structure, est nécessaire. L exemple suivant définit une structure d'objet d'un nouveau type Date, composé d'un champ entier JOUR, un champ MOIS de 3 caractères, e.g. "jan" "fev" etc., et d'un champ ANNEE qui est entier aussi. struct Date { int JOUR; char MOIS[3]; int ANNEE; ;

89 Chap. 8: Les structures 85 La structure Date peut éventuellement être utilisée pour des champs d une autre structure. On peut donc imbriquer les structures les unes dans les autres. Par exemple la structure suivante struct Etudiant{ string nom; char prenom[30]; char *adresse; int numero; struct Date D_Nais; ; utilise la structure Date pour l un de ses champs : D_Nais. Ce dernier est composé de JOUR, MOIS et ANNEE. Pour que cela fonctionne, comme pour les fonctions, il faut déclarer la structure Date au-dessus de la déclaration de la structure Etudiant. Bien souvent, les structures sont déclarées en début de programme ou dans un fichier en-tête, car elles seront certainement utilisées par l'ensemble des fonctions du programme. Maintenant, pour déclarer des variables du type d une structure, on peut écrire par exemple : struct point pt; point Z ; Client Cli1, Cli2; struct Date paques; struct Date semaine[7]; struct Etudiant Grp_1_A[20] ; struct Etudiant Anne, Jean ; // la variable pt est un point dont le type est "struct point". /* en C++ le mot clé struct n'est pas nécessaire devant la structure lors de la déclaration. struct point Z ; ou point Z ; sont équivalentes, cela signifie que Z est un point */ // Cli1 et Cli2 sont deux clients qui ont un nom et un Code. /* Le type de la variable paques est "struct Date". paques est la variable structurée composée de trois champs: JOUR, MOIS et ANNEE.*/ // semaine est un tableau de 7 éléments, chacun de type Date // Grp_1_A est un groupe de 20 étudiants // Anne et Jean sont deux nouvelles variables de type Etudiant La déclaration des variables peut se faire aussi au moment de la définition de la structure : struct Date { int JOUR; char MOIS[3]; int ANNEE; hier, demain; On se réfère aux champs individuels des variables par l'opérateur point., ainsi: demain.jour est l'entier JOUR. demain.mois[0] est le premier caractère du MOIS. demain.annee est l'entier ANNEE. semaine[0].jour est l'entier JOUR de la première composante du tableau semaine. Jean.D_Nais.JOUR est le JOUR de la date de naissance de Jean. Pour initialiser les variables de type struct déclarées précédemment, on peut le faire en accédant aux membres, par exemple:

90 Chap. 8: Les structures 86 pt.x=25; Cli1.Code = D ; Jean.D_Nais.JOUR = 15 ; Mais il est également possible d'initialiser une structure au moment de sa déclaration, en donnant la liste des valeurs de ses champs, de la même manière que pour un tableau. En reprenant l'exemple précédent, au moment de déclarer la variable pt ou Cli1, on peut écrire : struct point pt={25,10; struct Client Cli1{ "Van cool", 'D'; La variable pt (Cli1) est ici déclarée comme étant de type point (Client) et initialisée comme suit : son x=25 (nom= "Van cool") et son y=10 (Code = 'D'). Les initialisations d une structure à la déclaration ne peuvent pas être utilisées ailleurs qu'au moment des déclarations. Par exemple, l'écriture suivante est incorrecte: struct point pt;... pt = {25,10 ; // Ecriture incorrecte Si l on désire initialiser par exemple un étudiant lors de la déclaration de sa variable, on peut le faire comme suit : struct Etudiant JD = { "Dupont", "Jean", "rue de Houdain, 9, 7000 Mons", 402, { 15, "jan", 1986 ; En C++ le mot-clé struct n'est pas nécessaire devant la structure lors de la déclaration. En effet, les déclarations suivantes sont équivalentes : struct Etudiant Grp_1_A[20]; équivalent à Personne Grp_1_A[20] ; struct Etudiant Anne, Jean; équivalent à Personne Anne, Jean ; 8.2. Pointeurs vers les structures Il faut noter que ce point ne fait pas l objet de l enseignement durant cette année, mais bien de la matière donnée dans le cadre du cours d informatique en second Bachelier. Il est donné ici seulement à titre indicatif. Si la structure est un pointeur, comment peut-on accéder à ses membres? La déclaration suivante Personne *pp; déclare pp comme un pointeur vers une structure Etudiant. On peut écrire (*pp).numero

91 Chap. 8: Les structures 87 pour accéder au champ numero. L'opérateur. étant prioritaire sur l'indirection *, il faut des parenthèses. Mais il y a une autre notation d'utilisation. Au lieu de (*pp).numero, on utilise plutôt l'opérateur -> pour écrire plus simplement pp-> numero pour accéder au champ numero de la structure pointée par pp. Dans (*pp).numero, les parenthèses sont obligatoires à cause de la précédence de. sur *. Auparavant, on aura initialisé pp (ne pas l'oublier) par exemple par pp = &Grp_1_A[0] ou pp = Grp_1_A; 8.3. Structures et fonctions Les structures peuvent être passées en arguments de fonctions, par valeur ou par référence. Elles peuvent aussi être retournées par une fonction. On peut également utiliser l'affectation entre structures. Construisons par exemple une fonction module, qui donnera la distance euclidienne d'un point à l'origine. #include <cmath> float module ( point z) { float temp; temp = (z.x)*(z.x); temp += (z.y)*(z.y); return sqrt(temp); // pour utiliser la fonction racine carrée sqrt Nous pouvons de même construire une fonction qui calcule la somme de vecteurs. point somme(point a, point b) { point temp; temp.x = a.x + b.x; temp.y = a.y + b.y; return temp; Les appels suivants de ces fonctions seront corrects: point z1 = {1, -4, z2 = {5, 2, z3; if( module(z1) > 1.0 ) z3 = somme( z1, z2 ); ce qui donnera z3 = (6, -2). Le programme suivant nous montre comment retourner une référence. Nous invitons le lecteur à le tester et déduire comment il fonctionne.

92 Chap. 8: Les structures 88 #include <iostream> #include <string> using namespace std; struct Client { string nom; string adresse; char Code; ; /* utilisation de l espace de nommage std pour importer les symboles de la bibliothèque standard C++ */ Client quel_client(int i, Client DataBase[]) { if ((i > 0) && (i < 4 )) return(database[i]); else return(database[0]); void main(void) { int N; Client DataBase[4] = { {"Picsou", "Pas de sous 00", 'B', {"Donald", "Bcp de sous 123", 'D', {"Obelix", "Village gaulois 15", 'G', {"BISCORNUS", "BABAORUM 2341", 'M' ; cout << "Pour chercher un Client, donner un numero entre 1 et 4 : "; cin >> N; cout << "Debut de recherche du Client " << N << endl; Client ce_client = quel_client(n-1, DataBase); cout << "\n NOM : " << ce_client.nom << "\n Adresse : " << ce_client.adresse << "\n Code : " << ce_client.code << endl; Programme 8.1 Le programme suivant illustre aussi l utilisation des structures lors du passage de paramètres par valeur et par référence. #include <iostream> using namespace std; struct point { int x; int y; ;

93 Chap. 8: Les structures 89 point creer_pt () { // retourne une structure point res = { 10, 20 ; return res; void affiche(point le_pt, char titre[]){ cout << titre << " x= "<< le_pt.x << " y= "<< le_pt.y << endl; void pt_par_valeur ( point le_pt ) { le_pt = creer_pt(); affiche(le_pt, "Dans pt_par_valeur : "); void pt_par_pointeur ( point *le_pt ){ *le_pt = creer_pt(); affiche(*le_pt, "Dans pt_par_reference : "); void pt_par_reference ( point & le_pt ){ le_pt = creer_pt(); affiche(le_pt, "Dans pt_par_reference : "); void main (){ point mon_pt; mon_pt.x= mon_pt.y=0; affiche(mon_pt, "contenu initial de 'mon_point':\n"); pt_par_valeur (mon_pt); affiche(mon_pt, "Main Sortie de pt_par_valeur \n"); mon_pt.x= mon_pt.y=0; pt_par_pointeur (&mon_pt); affiche(mon_pt, "Main Sortie de pt_par_pointeur \n"); mon_pt.x= mon_pt.y=0; pt_par_reference (mon_pt); affiche(mon_pt, "Main Sortie de pt_par_reference \n"); Programme 8.2 Le résultat de ce programme est : contenu initial de 'mon_point': x= 0 y= 0 Dans pt_par_valeur : x= 10 y= 20 Main Sortie de pt_par_valeur x= 0 y= 0 Dans pt_par_reference : x= 10 y= 20 Main Sortie de pt_par_pointeur x= 10 y= 20 Dans pt_par_reference : x= 10 y= 20 Main Sortie de pt_par_reference x= 10 y= 20 Le programme suivant doit saisir un tableau de structures, afficher un certain nombre de champs du tableau, échanger deux composants du tableau et finalement libérer la mémoire.

94 Chap. 8: Les structures 90 #include <iostream> #include <string> #include <iomanip> //pour setw(x):la prochaine sortie sera sur une largeur de x using namespace std; const int NE_max=20; const int NC_max=30; struct Date { int JOUR, MOIS, ANNEE; ; struct Personne{ char nom[nc_max]; string prenom; int numero; struct Date D_Nais; ; Personne saisie (); void affichage (Personne Tab[], int taille); void echanger(personne &Tab1, Personne &Tab2); void liberer(personne Tab[], int taille); void main( ){ int i=0, NE; Personne Tab[NE_max]; cout <<"Combien d'etudiants voulez-vous introduire (entre 1 et " << NE_max << ")? "; cin >> NE; while (i<ne){ Tab[i]=saisie(); // (1) i++; affichage (Tab, NE); // (2) if(ne>2){ echanger(tab[1], Tab[2]); // (3) affichage (Tab, NE); Personne saisie (){ Personne tmp; int static j=0; // voir chapitre 5! j++; cout << "\nnom_"<< j << " : "; cin >> tmp.nom; cout << "\nprenom_"<< j << " : "; cin >> tmp.prenom; cout << "\nnumero_"<< j << " : "; cin >> tmp.numero; cout << "\njour : "; cin >> tmp.d_nais.jour; cout << "\nmois : "; cin >> tmp.d_nais.mois; cout << "\nannee : "; cin >> tmp.d_nais.annee; return tmp;

95 Chap. 8: Les structures 91 void affichage (Personne Tab[], int taille){ int i=0; while (i<taille){ cout <<setw(20) << Tab[i].nom <<setw(20) << Tab[i].prenom <<setw(5) << Tab[i].D_Nais.ANNEE<< endl; i++; cout << "\n\n"; void echanger (Personne &Tab1, Personne &Tab2){ Personne temp; temp = Tab1; Tab1 = Tab2; Tab2 = temp; // (3') Programme 8.3 La fonction main appelle (1) la fonction sans paramètres : saisie(). Cette dernière est de type Personne, donc doit absolument retourner une valeur de même type. En effet, cette fonction saisit les données pour une personne et retourne cette personne à la fonction main(). La fonction affiche (2) permet d afficher quelques champs pour chaque élément du tableau. La fonction echanger (3) a pour rôle d échanger les données de deux éléments du tableau. Pour que le changement se transmette à la fonction appelante, nous avons utilisé les références de ces enregistrements. Il faut noter, que si l on ne peut affecter un tableau à un autre, les structures le permettent. L affectation ne se fait pas champ par champ mais structure par structure (3 ) même si cette dernière contient un tableau.

96 Chap. 8: Les structures 92 Ce qu il faut au moins retenir : La déclaration d une structure : struct ma_struct { int x; float y; ; Si le tableau est une collection de variables de même type, une structure est un ensemble de variables de types éventuellement différents. Si l affectation d un tableau à un autre est interdite, il est possible d assigner une structure à une autre, même si un élément de la structure est un tableau. Le point-virgule après l'accolade fermante de la déclaration d une structure est obligatoire. On ne peut utiliser une structure A dans une structure B que si A est déclarée avant B. On se réfère aux champs individuels des variables de type structure par : A.champ1 ou A->champ1 si A est une structure sur un pointeur. Exercices 8.0. Ecrire une fonction qui traduit le graphique (température en fonction de x) suivant : 25 t température en fct x x Ecrire un programme qui traite un tableau de structures (taille max = 20) dont chaque élément comprend les informations suivantes : un nom ( string nom), un numero (int), une date où date est une structure de type Date struct Date{ int jour, mois, an ; ; qui gère en boucle le menu de choix suivant :

97 Chap. 8: Les structures 93 1 : Saisie des enregistrements 2 : Affichage des données 3 : Tri suivant le numéro 4 : Tri suivant le nom 5 : Effacer un élément selon le nom 6 : Ajouter un élément selon le nom 7 : Sauvegarde sur fichier 8 : Lecture d un fichier 9 : Quitter Le menu sera affiché via une fonction, les choix seront traités via l instruction case. Les points 1 à 8 seront chacun traités par au moins une fonction. Les points 5 et 6 utiliseront la recherche dichotomique pour la localisation. Le point 8 utilisera un vecteur crée dynamiquement pour recevoir les données se trouvant dans le fichier Ecrire le même programme que 8.1. en remplaçant la structure par : struct Etudiant{ char *nom ; int numero ; char code ; ; 8.3. Ecrire le même programme que 8.1. en remplaçant la structure par : struct Etudiant{ string nom ; int numero ; int Matieres[3] ; ; 8.4. Donnez la structure représentant ce tableau : Nom Adresse Sexe res1 res2 resn Code Myne nom1 nom2 56 rue je ne sais pas, bte 10, 33, rue qui n existe pas, M A 13.3 F V 15.7 nom3 M C 13.9 nom20 F D 10.2

98 Chap. 8: Les structures Enoncé Ecrire un programme permettant de manipuler un tableau d enregistrements structures (taille max NE_MAX = 20). Ce programme doit gérer en boucle le menu suivant : 3 - SUPPRESSION d'un élément après localisation Nom de l élément à supprimer : van cool Code de l élément à supprimer : A 1 - SAISIE et AFFICHAGE du tableau 2 - TRI par ordre alphabétique selon le nom et le code 3 - SUPPRESSION d'un élément après localisation 4 - Sauvegarde 5 - ARRET du programme La structure de chaque élément est : struct Element { string nom char code int cotes[nc_max] ; // NC_max=5 1 - SAISIE et AFFICHAGE est constitué de deux fonctions : Saisie (...) ; // de type void Dans cette fonction, on demandera le nombre d éléments (NE) pour initialiser le tableau (par exemple 5) et le nombre de cotes (NC<=5) pour tous les "ELEMENT", et on effectuera la saisie du nom, du code et des cotes pour chaque élément. Affichage(.) ; Après la saisie, une fonction d affichage est appelée afin d afficher l acquisition de la fonction saisie. Exp : si NE=5 et NC=2 Nom Code Cote1 Cote2 van cool P mon_nom M 2 1 son_nom T 29 2 van cool A aladdin Y TRI par ordre alphabétique selon le nom et le code La liste devient (Fonction AFFICHAGE ) : Nom Code Cote1 Cote2 aladdin Y mon_nom M 2 1 son_nom T 29 2 van cool P Avant de supprimer l élément avec la fonction Suppression, il faut d abord le localiser avec la fonction Localisation (dichotomique) RQs: Si l élément à supprimer n existe pas, n oubliez pas de le signaler à l utilisateur. Le programme doit utiliser une série de fonctions qui vont permettre de séparer les tâches. 4 - Sauvegarde On demandera à l utilisateur d introduire un seuil (int). Ce dernier doit être >0 et < 100 (test). Pour chaque "ELEMENT", si la somme de ses cotes est supérieure au seuil, on l enregistrera dans un fichier Fich.txt. Exp : Seuil = 80 Dans le fichier aladdin Y van cool P Nom Code Cote1 Cote2 aladdin Y mon_nom M 2 1 son_nom T 29 2 van cool A van cool P 45 54

99 Chap. 8: Les structures 95 Enoncé 8.6. A- Actualisation et affichage : Ecrire un programme permettant de manipuler un tableau d enregistrements "structure" (NP_max = 20) dont chaque élément comprend les informations suivantes Ligne{ string Phrase ; Compt ; // une structure avec Compt est une structure de type : Compt{ int N_e ; int N_i ; int Som; Réaliser un programme qui gère en boucle le menu de choix suivant : S- Saisie et affichage T- Tri et affichage A- Actualisation et affichage V- Valeurs Q- Quitter Pour chaque ligne, on compte le nombre de e, de i et on détermine Som= N_e+N_i. Puis on actualise la structure (N_e, N_i et Som ). Enfin, on affiche l actualisation du tableau. EXP : TEXTE N_e N_i Som qui compte le nombre de e et de i ainsi ceci est un test la longueur de la ligne Dans la fonction Actualisation on cherche le max de Som (Max_Som) et sa position (pos) dans le tableau. V_ Valeurs : Affiche les nombres : NL, Max_Som et pos. S- Saisie et affichage : La fonction saisie (de type void) demande à l utilisateur le nombre de "Ligne" (NL) pour initialiser le tableau (par exemple 5) et lui permet d introduire un texte par ligne. EXP : saisie( ) puis affichage(.) Ligne_1 : ceci est un test Ligne_2 : qui compte le nombre Ligne_3 : de e et de i ainsi Ligne_4 : la longueur de Ligne_5 : la ligne Remarques: Il est souhaitable d utiliser la même fonction Affichage en S, T et A. (une et une seule fonction) NL, Max_Som et pos sont des variables locales de la fonction main. NP_max et dim_max sont des constantes.! T- Tri et affichage : Tri décroissant selon la longueur du texte par ligne(fonction) puis affichage(fonction). qui compte le nombre 20 de e et de i ainsi 18 ceci est un test 16 la longueur de 14 la ligne 8

100 Chap. 8: Les structures Le boulier à quatre Ce qu on appelle boulier à quatre, c est un système de billes suspendues par des fils. Ce système accepte au maximum quatre billes (un tableau de 4 éléments). Au-delà de quatre, si une bille est ajoutée à droite, la bille de gauche est retirée. De même, si une bille est ajoutée à gauche, celle de droite est retirée. Ecrire un programme permettant de représenter cette application. Chaque bille est représentée par une structure contenant les données suivantes : string Couleur_Bil; // couleur de la bille par exemple : vert bouteille char Code ; // 1 seul caractère et pas un tableau d un seul caractère Code[1] Le programme doit gérer en boucle le menu de choix suivant : 1- Saisie et Affichage 2- Ajout Gauche et Affichage 3- Ajout Droite et Affichage 4- Affichage 5- Effacer bille et Affichage + Sauver Fichier 6- Sortir Exemple d exécution 1- Saisie et Affichage : Dans la fonction saisie (Type void), on demandera à l utilisateur le nombre de billes (NI<=4) pour initialiser le Tableau. Exp : Si NI=2 //couleur (Code) Rouge (E) Vert bouteille (C) Ajout Gauche et Affichage : R V B Bleu (T) Bleu (T) Rouge (E) Vert bouteille (C) Ajout Droite et Affichage : B R V B Blanc (S) Bleu (T) Rouge (E) Vert bouteille (C) Blanc (S) 2- Ajout Gauche et Affichage : Jaune (T) Jaune (T) Bleu (T) Rouge (E) Vert bouteille (C) B J R B V B R Bc V B 2- Ajout Gauche et Affichage : Noire (N) Noire (N) Jaune (T) Bleu (T) Rouge (E) N J B R 5- Effacer bille et Affichage + Sauver Fichier // La bille est choisie par l utilisateur Il faut se baser aussi sur le code (Si deux billes de même couleur). Couleur de la bille : Jaune Code : T Noire (N) Bleu (T) Rouge (E)... Fichier Jaune T Si la bille à effacer existe, il faut la supprimer du tableau et l enregistrer dans un fichier Fich.txt. Remarques : Utilisez les règles de bonnes pratiques étudiées durant les travaux pratiques telles que l indentation syntaxique, la programmation modulaire, Votre programme utilisera une série de fonctions permettant de séparer les tâches (Saisie, Affichage, Ajout, Localiser, Sauver ). Il doit empêcher l utilisateur de se retrouver avec un tableau de plus que quatre billes ou d en effacer une alors qu il est vide. Si la bille à supprimer n existe pas, n oubliez pas de le signaler à l utilisateur. N B R

101 Chap. 8: Les structures Rythme cardiaque et sport : seuil de lipolyse Il est très utile à nombre d'entre nous de définir à quel rythme cardiaque effectuer nos exercices physiques. En premier lieu pour pratiquer nos activités en toute sécurité et ensuite, pour savoir tout simplement à quel moment notre organisme puise dans ses réserves de graisses, c'est ce qu on appelle le seuil de lipolyse. Il semble que c est cette fréquence cardiaque (seuil de lipolyse) qu il faut maintenir pendant la durée des activités sportives afin de maigrir. Ce seuil peut être calculé comme suit: (220 - âge - fréquence cardiaque au repos) divisé par deux + fréquence cardiaque au repos Par exemple, quelqu'un âgé de 25 ans et dont le rythme cardiaque au repos est de 70 battements par minute : (âge) 70 (fréquence cardiaque au repos) = 125 ; 125/2 = 62 ; = 132 Son seuil de lipolyse est de 132 battements cardiaques par minute. Ecrire un programme permettant de manipuler un tableau de personnes (taille max Nmax = 6 ) dont chaque élément comprend les informations suivantes : { string Nom ; int Age; int FreqR ; // fréquence cardiaque au repos IL EST INTERDIT DE MODIFIER LA STRUCTURE ; Ce programme doit gérer en boucle le menu suivant : 1- Saisie et Affichage 2- AAffiffichachagege 3- Seuil de lipolyse et Affichage 4- Effacer et Affichage 5- Tab Dynamique et affichage 3- Seuil de lipolyse et Affichage: Ici on calcule le seuil de lipolyse pour chaque personne et on affiche les résultats. Nom Age FreqR Seuil Lipo Riri Fifi Lou Lou Effacer et Affichage: Est constitué de deux fonctions : Effacer (.) et Affichage Effacer (.) ; Dans cette fonction on demandera à l utilisateur d introduire une valeur V (de type int). Cette dernière doit être >10 et < 50 (tester). On supprimera ensuite du tableau chaque personne dont l âge est strictement inférieur à V.! 1- Saisie et Affichage: Est constitué de deux fonctions : Saisie (.) ; // Type void Dans cette fonction on demandera le nombre d éléments NE (<Nmax :tester) à saisir et on effectuera la saisie des éléments. Affichage(.) ; Permet l affichage des données : EXP : Si NE=3 Nom Age FreqR Riri Fifi Lou Lou AAffiffichachagege: Permet d afficher deux fois chaque ligne: Nom Age FreqR Riri Riri Fifi Fifi Lou Lou Lou Lou RQ : Il est fort souhaitable d utiliser la même et seule fonction Affichage en 1, 2, 3 et 4. EXP : Si V = 35 le tableau deviendra Nom Age FreqR Seuil Lipo Fifi Tab Dynamique et affichage: On désire ici avoir les résultats pour tracer la courbe de l âge en fonction du rythme cardiaque. Donc, pour une FreqR F, donnez le Seuil de Lipolyse pour une tranche d âge entre 15 et 45 avec un pas P. F et P seront demandés à l utilisateur. Exp1 : Si F= 70 et P= 5 on aura : Age 15, 20, 25, 30, 35, 40, 45 Seuil Exp2 : Si F= 70 et P= 10 on aura : Age 15, 25, 35, 45 Seuil Selon la valeur de P, la dimension du tableau (âge, seuil) change. C est pour cette raison qu il faut utiliser un tableau dynamique pour stocker et afficher les résultats (âge, seuil). RQs : Les variables globales sont à éviter.

102 Chapitre 9: Les listes simplement chaînées 9.1. Généralités Jusqu'à présent, nous n'avons travaillé qu'avec des structures de données statiques, dont l'espace mémoire occupé pouvait être défini avant l'exécution. Dans le cas d une déclaration d un tableau de structure par la syntaxe: struct Etudiant Tab[100] ; Cette déclaration permet de réserver automatiquement une zone mémoire d une longueur de 100 éléments de type Etudiant. Les cellules du tableau sont alors accessibles par Tab[0] à Tab[99]. Cependant, le problème réside dans le fait que la déclaration du tableau avec une dimension constante fige le nombre d éléments de ce tableau. Autrement dit, même si un programme n a besoin que de 20 éléments, on réservera malgré tout 100 cellules de type Etudiant. Comme nous l avons déjà vu en 1 ère Bachelier, nous pouvons remédier à cela en utilisant les pointeurs. Les instructions deviennent dans ce cas-ci : struct Etudiant *Tab; Pour pouvoir stocker en mémoire une valeur de type Etudiant, il faut donc explicitement demander une adresse disponible en utilisant le mot réservé new et la libérer avec delete. L allocation dynamique de la mémoire correspondant au nombre de cellules est maintenant au gré de l utilisateur. On peut, par exemple, lui demander d introduire un nombre N, puis nous réservons l espace mémoire strictement nécessaire. cout<< " Dimension du Tableau N : " ; cin >> N; // Allocation mémoire : new[] Tab = new Etudiant[N]; // Restituer la mémoire : delete[] delete[] Tab; Supposons qu à un moment donné dans le programme même, nous n ayons plus besoin que de (N-5) éléments. La logique, comme nous désirons optimiser la gestion de la mémoire, est de libérer la place de mémoire pour 5 cellules. Mais cela ne peut se faire ni automatiquement ni directement. Donc cela reste bien sûr limitatif. En effet, cela ne permet pas d'exploiter les structures tels que les listes chaînées, les piles, les arbres, structures fondamentales pour de nombreux algorithmes. Structures de données et algorithmes 9.2. Listes Simplement chaînées Une liste chaînée est une séquence d'objets dynamiques dont chacun contient une indication explicite vers l'élément suivant. Une liste est faite de cellules. Chaque cellule contient un élément de la liste et l'adresse de l'élément suivant (structure de même type). Considérons donc la définition d'une liste simplement chaînée de structures contenant des strings. "Etud1" "Etud2" "Etud3" NULL

103 Chap. 9: Les listes simplement chaînées 99 Chaque cellule de la liste chaînée peut être définie comme une structure: struct Etudiant { string Nom; struct Etudiant *next; ; // Etudiant suivant Chaque cellule comporte donc une zone mémoire pour stocker son contenu (ici string Nom), ainsi qu'une zone mémoire pour stocker un pointeur vers la cellule suivante (c'est-à-dire l'adresse de la cellule suivante). Pour pouvoir travailler avec une liste simplement chaînée, il faut connaître l'adresse de sa première cellule. Nous définirons donc un pointeur: struct Etudiant *debut; // ou simplement Etudiant *debut; Si les tableaux permettent un accès direct aux éléments, les listes chaînées en sont dépourvues. La définition et la nature même de la liste chaînée font apparaître que l on ne peut parcourir intégralement la liste qu en partant du premier élément et en visitant les éléments l un après l autre. En contrepartie nous gagnons en souplesse lorsqu il s agit de modifier la liste. Des opérations telles que : ajout, suppression d un élément à une position quelconque dans la liste, la suppression avec libération de mémoire d un nombre quelconque d éléments consécutifs, Voici un programme simple mais complet, dans lequel nous traitons un certain nombre d opérations sur la liste. Par exemple : l'insertion d'une nouvelle cellule en début de liste, le parcours de la liste pour l affichage, l effacement d'une cellule, la libération de la mémoire. #include <iostream> #include <string> using namespace std ; struct Etudiant{ string Nom; struct Etudiant *next; ; // le lien : pointeur sur la cellule suivante //insérer un nouvel élément en tête de Etudiant et retourner un pointeur Etudiant *insere_en_tete(string x, Etudiant *lis ) { Etudiant *c; c = new Etudiant ; // créer une cellule if (c!=null){ c->nom=x; // assignation de x c->next=lis; // assignation de suivant: chaîner avec la première cellule de la Etudiant lis=c; return (lis); // chaînage: faire pointer la tête de Etudiant vers la nouvelle cellule. void parcours (Etudiant *lis) { Etudiant *p; p = lis;

104 Chap. 9: Les listes simplement chaînées 100 cout << "Affichage : "<< endl; while ( p!= NULL) { cout << p->nom << endl; p = p->next; cout <<endl<<endl; void liberation (Etudiant *lis) { Etudiant *p; p = lis; while ( p!= NULL) { // si p=null, donc fin de Etudiant lis=lis->next; delete p; p = lis; void main() { int i, n; string Name; Etudiant *debut; debut=null; // Etudiant vide cout << "nombre d'elements N: " ; cin >> n; cout << "\n Creer un Etudiant avec insertion en tete de Etudiant + affichage \n"; for(i=1; i<=n; i++){ cout << "\n Nom "<< i << " : "; cin >> Name; debut=insere_en_tete(name, debut); parcours(debut); // Affichage // cout << "Inserer une nouvelle cellule apres la cellule debut " << endl; Etudiant *p; p = new Etudiant; p->nom = "Nouveau"; p->next = debut->next; debut->next = p; parcours (debut); // cout << "Supprimer la 1ere cellule " << endl; Etudiant *q; q=debut; debut=debut->next; delete q; // mémoire dynamique n'est plus utilisée -> doit être libérée. parcours (debut); // // Libération cout << " Liberation de la memoire "; liberation (debut);

105 Chap. 9: Les listes simplement chaînées 101 nombre d'elements N: 3 Creer une liste avec insertion en tete de liste + affichage Nom 1 : premier Nom 2 : second Nom 3 : nom3 S O L U T I O N Affichage : nom3 second premier Inserer une nouvelle cellule apres la cellule debut Affichage : nom3 Nouveau second premier Supprimer la 1ere cellule Affichage : Nouveau second premier Liberation de la memoire

106 Chapitre 10: Quelques erreurs à éviter Ce chapitre n aurait pas pu être rédigé sans l aide d un certain nombre d étudiants. En effet, il a été alimenté par des erreurs que certains d entre eux ont commises lors des séances de travaux voire à l examen. La devise C est en faisant des erreurs que l on apprend me pousse à montrer celles commises par les anciens étudiants afin de permettre aux nouveaux de ne pas commettre les mêmes, au moins je l espère. La plupart des erreurs décrites ici sont des erreurs d'inattention ou proviennent de la syntaxe du langage combinée à l'inattention du programmeur. En raison de la puissance d'expression du langage et du peu de vérifications réalisées par le compilateur, de nombreuses erreurs sont possibles. Certaines d entre-elles ne seront pas détectées à la compilation mais produiront nécessairement des erreurs plus ou moins faciles à détecter à l'exécution. Certaines de ces erreurs conduisent systématiquement à un plantage du programme en cours d'exécution ou à un résultat faux, alors que d'autres conduisent à des comportements indéterminés, c'est-à-dire que n'importe quoi peut se produire. Déclaration : Int i,j, Correction int i, j ; Une déclaration se termine par un point virgule et le type des variables doit être écrit en minuscule. En effet le C fait la différence entre les minuscules et les majuscules. Affectation: int A, B ; A=10 ; A=B ; Correction int A, B ; A=10 ; B=A ; Le rôle du symbole d affectation = consiste à évaluer l expression du membre de droite et à transférer ce résultat comme valeur de l objet au membre de gauche. Donc pour affecter la valeur de A c.-à-d. 10 à B, il faut écrire B=A à la place de A=B. D ailleurs on écrit A=10 et pas 10=A. void main(){ int *adr; *adr = 123;... Correction void main(){ int *adr; adr = new int; *adr1 = 123;... delete adr; La valeur d'un pointeur désigne l'adresse de la zone mémoire vers laquelle il pointe. Si cette adresse ne correspond pas à une zone de mémoire utilisable par le programme en cours, une erreur (segmentation fault) se produit à l'exécution du programme. Mais, même si l'adresse est valide et ne produit pas d'erreur, il faut s'assurer que la valeur du pointeur correspond à une zone allouée correctement, avec new et libérer avec delete. int A, B ; float F; A=10 ; B=25 ; F= B/A ; Correction int A, B ; float F; A=10 ; B=25 ; F= (float)b/a ;

107 Chap. 10: Quelques erreurs à éviter 103 Taille d une chaîne : char nom[30] ; int taille ; cout <<"nom ="; cin >> nom ; taille = sizeof(nom); Correction Selon la déclaration de type de nom. int taille ; taille = strlen(nom); ou taille = nom.length() L opérateur sizeof nous donne le nombre d octets que le tableau nom occupe en mémoire et non le nombre de caractères que l utilisateur à introduit. Saisie et/ou affichage : int i ; cout <<"valeur de i = " << i; Correction int i ; i=5; //Initialiser la variable avant cout <<"valeur de i = " << i; Dans cet exemple, la valeur de i n est pas initialisée, donc l affichage peut être n importe quoi. Confusion entre = et = = : if (x = 0) {... Correction if (x == 0) {... Cette erreur est l'une des plus fréquentes, elle provient de la syntaxe du langage combinée à l'inattention du programmeur. Elle peut être très difficile à détecter. En effet, x = 0 est une expression valide en C/C++ qui affecte à x la valeur zéro, il est donc parfaitement légal d'écrire if (x = 0) { Malheureusement le programmeur voulait tester si x valait zéro? Cela entraîne que, même quand x est différent de 0, la variable x prend la valeur 0! Cependant, ce problème n'est pas limité au cas de la comparaison avec une constante. Il se pose aussi lorsque l'on veut comparer deux variables. Cette erreur n est pas propre à if..else, mais on peut la rencontrer dans les boucles conditionnelles à l endroit de <expression logique > ( voir la section 3.3. ). Boucles conditionnelles : for (i = 0, i<n, i++){ Correction for (i = 0 ; i<n; i++){ ; et non, for (i = 0 ; i<n; i++) ; { Correction for (i = 0 ; i<n; i++) { int Tab[N]; for (i = 0 ; i == N; i++){ Tab[i]=i; Correction int Tab[N]; for (i = 0 ; i<n; i++){ Tab[i]=i; M.BENJELLOUN Struct. D.A S. Informatique

108 Chap. 10: Quelques erreurs à éviter 104 Une boucle qui ne fait pas ce que l on désire, c est-à-dire exécuter le bloc d instruction(s) pour i=0, i=1, etc. Elle ne le fait que quand i vaut N. Malheureusement, en plus dans ce cas-ci, il ne faut pas aller jusqu à N (voir la définition d un tableau ). int Tab[N]; for (i = 0 ; i<n; i++) Tab[i]=i; cout << "Tab[i]= " << i; Correction int Tab[N]; for (i = 0 ; i<n; i++) { Tab[i]=i; cout << "Tab[i]= " << I; Avec une boucle conditionnelle, s il faut exécuter plusieurs instructions, il faut les mettre entre { et. while (<expression logique >); {... Correction while (<expression logique >) {... Pas de ; juste après le while, sinon c est une boucle qui ne fait qu attendre. Oubli du break dans les switch : void print_chiffre(int i) { switch (i) { case 1: cout <<"un"; case 2: cout <<"deux"; case 3: cout <<"trois"; Correction void print_chiffre(int i) { switch (i) { case 1: cout <<"un"; break; case 2: cout <<"deux"; break; case 3: cout <<"trois"; break; default : cout <<"1,2 ou 3?"; Sans les break l appel de la fonction print_chiffre(1) affichera undeuxtrois ce qui n'est peut-être pas le comportement attendu. L étiquette default est facultative mais recommandée. Fonctions : int Cube(int i) { i*i*i; Correction int Cube(int i) { return(i*i*i); void Cube(int &i) { i = i * i * i; int Deux_val(int i, int j){ return (i,j); int Deux_val(int i, int j) { return i; return j; Correction void Deux_val(int &i, int &j) { i = j = void Modif(int *i, int *j) { i = 5; j = 6; Correction void Modif(int *i, int *j) { *i = 5; *j = 6; M.BENJELLOUN Struct. D.A S. Informatique

109 Chap. 10: Quelques erreurs à éviter 105 void Modif(int *i, int *j) { *i = 5; *j = 6; void main(){ int k,j ; Modif(k, j); void Modif(int i, int j) { i = 5; j = 6; void main(){ int k,j ; Modif(k, j); Correction void Modif(int *i, int *j) { *i = 5; *j = 6; void main(){ int k,j ; Modif(&k, &j); void Modif(int &i, int &j) { i = 5; j = 6; void main(){ int k,j ; Modif(k, j); int Modif(int i) { i = 5; return i; void main(){ int j ; Modif(j); cout<< j; Correction int Modif(int i) { i = 5; return i; void main(){ int j ; j=modif(j); cout<< j; int Modif(int i) { i = 5; return i; void main(){ int j ; cout<< Modif(j); void Modif(int &i) { i = 5; void main(){ int j ; Modif(j); cout<< j; int Fonc(int Tab[], int N){ int i; for (i = 0 ; i<n; i++) Tab[i]=i; return Tab; void Saisie1(int Tab1[], int N1){ int i; for (i = 0 ; i<n1; i++) Tab1[i]=i; void Saisie2(int Tab2[], int N2){ int i; for (i = 0 ; i<n2; i++) Tab2[i]=i; void main(){ int Tab1[40], Tab2[40]; int N1=20, N2=30; saisie1(tab1, N1) ; saisie2(tab2, N2) ; struct Article{ string nom; ; void main() { Article T[5]; for (int i=0; i<5; i++){ cout << "Entrez le nom : "; cin >> T.nom; Correction Correction Correction void Fonc(int Tab[], int N){ int i; for (i = 0 ; i<n; i++) Tab[i]=i; /*une fonction ne peut retourner un tableau avec return */ void Saisie(int Tab[], int N){ int i; for (i = 0 ; i<n; i++) Tab[i]=i; void main(){ int Tab1[40], Tab2[40]; int N1=20, N2=30; saisie(tab1, N1) ; saisie(tab2, N2) ; struct Article{ string nom; ; void main() { Article T[5]; for (int i=0; i<5; i++){ cout << "Entrez le nom : "; cin >> T[i].nom; M.BENJELLOUN Struct. D.A S. Informatique

110 FACULTÉ POLYTECHNIQUE DE MONS Service d Informatique Annexes

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3. 1. Structure d un programme C Un programme est un ensemble de fonctions. La fonction "main" constitue le point d entrée pour l exécution. Un exemple simple : #include int main() { printf ( this

Plus en détail

Licence ST Université Claude Bernard Lyon I LIF1 : Algorithmique et Programmation C Bases du langage C 1 Conclusion de la dernière fois Introduction de l algorithmique générale pour permettre de traiter

Plus en détail

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP COURS PROGRAMMATION INITIATION AU LANGAGE C SUR MICROCONTROLEUR PIC page 1 / 7 INITIATION AU LANGAGE C SUR PIC DE MICROSHIP I. Historique du langage C 1972 : naissance du C dans les laboratoires BELL par

Plus en détail

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation impérative et structures de données simples Introduction au langage C Sandrine Blazy - 1ère année 24 octobre 2007 Cours d Algorithmique-Programmation

Plus en détail

Introduction à l algorithmique et à la programmation M1102 CM n 3

Introduction à l algorithmique et à la programmation M1102 CM n 3 Introduction à l algorithmique et à la programmation M1102 CM n 3 DUT Informatique 1 re année Eric REMY eric.remy@univ-amu.fr IUT d Aix-Marseille, site d Arles Version du 2 octobre 2013 E. Remy (IUT d

Plus en détail

Introduction au Langage de Programmation C

Introduction au Langage de Programmation C Faculté Polytechnique de Mons Service d'informatique Introduction au Langage de Programmation C Mohammed Benjelloun 1 ère Candidature Année académique 2003-2004 Avant-propos Ces notes permettent de se

Plus en détail

Cours d Algorithmique et de Langage C 2005 - v 3.0

Cours d Algorithmique et de Langage C 2005 - v 3.0 Cours d Algorithmique et de Langage C 2005 - v 3.0 Bob CORDEAU cordeau@onera.fr Mesures Physiques IUT d Orsay 15 mai 2006 Avant-propos Avant-propos Ce cours en libre accès repose sur trois partis pris

Plus en détail

Algorithmique et Programmation, IMA

Algorithmique et Programmation, IMA Algorithmique et Programmation, IMA Cours 2 : C Premier Niveau / Algorithmique Université Lille 1 - Polytech Lille Notations, identificateurs Variables et Types de base Expressions Constantes Instructions

Plus en détail

Introduction au langage C

Introduction au langage C Introduction au langage C Cours 1: Opérations de base et premier programme Alexis Lechervy Alexis Lechervy (UNICAEN) Introduction au langage C 1 / 23 Les premiers pas Sommaire 1 Les premiers pas 2 Les

Plus en détail

UE C avancé cours 1: introduction et révisions

UE C avancé cours 1: introduction et révisions Introduction Types Structures de contrôle Exemple UE C avancé cours 1: introduction et révisions Jean-Lou Desbarbieux et Stéphane Doncieux UMPC 2004/2005 Introduction Types Structures de contrôle Exemple

Plus en détail

UE Programmation Impérative Licence 2ème Année 2014 2015

UE Programmation Impérative Licence 2ème Année 2014 2015 UE Programmation Impérative Licence 2 ème Année 2014 2015 Informations pratiques Équipe Pédagogique Florence Cloppet Neilze Dorta Nicolas Loménie prenom.nom@mi.parisdescartes.fr 2 Programmation Impérative

Plus en détail

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java Info0101 Intro. à l'algorithmique et à la programmation Cours 3 Le langage Java Pierre Delisle, Cyril Rabat et Christophe Jaillet Université de Reims Champagne-Ardenne Département de Mathématiques et Informatique

Plus en détail

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux. UEO11 COURS/TD 1 Contenu du semestre Cours et TDs sont intégrés L objectif de ce cours équivalent a 6h de cours, 10h de TD et 8h de TP est le suivant : - initiation à l algorithmique - notions de bases

Plus en détail

Claude Delannoy. 3 e édition C++

Claude Delannoy. 3 e édition C++ Claude Delannoy 3 e édition Exercices Exercices C++ en en langage langage delc++ titre 4/07/07 15:19 Page 2 Exercices en langage C++ AUX EDITIONS EYROLLES Du même auteur C. Delannoy. Apprendre le C++.

Plus en détail

Programmation en langage C

Programmation en langage C Programmation en langage C Anne CANTEAUT INRIA - projet CODES B.P. 105 78153 Le Chesnay Cedex Anne.Canteaut@inria.fr http://www-rocq.inria.fr/codes/anne.canteaut/cours C 2 Table des matières 3 Table des

Plus en détail

Cours de C++ François Laroussinie. 2 novembre 2005. Dept. d Informatique, ENS de Cachan

Cours de C++ François Laroussinie. 2 novembre 2005. Dept. d Informatique, ENS de Cachan Cours de C++ François Laroussinie Dept. d Informatique, ENS de Cachan 2 novembre 2005 Première partie I Introduction Introduction Introduction Algorithme et programmation Algorithme: méthode pour résoudre

Plus en détail

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Structure d un programme et Compilation Notions de classe et d objet Syntaxe Cours1 Structure d un programme et Compilation Notions de classe et d objet Syntaxe POO 1 Programmation Orientée Objet Un ensemble d objet qui communiquent Pourquoi POO Conception abstraction sur les types

Plus en détail

IN 102 - Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

IN 102 - Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C IN 102 - Cours 1 Qu on le veuille ou non, les systèmes informatisés sont désormais omniprésents. Même si ne vous destinez pas à l informatique, vous avez de très grandes chances d y être confrontés en

Plus en détail

SUPPORT DE COURS. Langage C

SUPPORT DE COURS. Langage C Dpt Informatique 2010-2011 SUPPORT DE COURS Langage C Semestre 1 par : «CaDePe» Marie-Françoise Canut Marianne de Michiel André Péninou Table des Matières 1 Généralités...8 1.1 Introduction aux langages

Plus en détail

COMPARAISONDESLANGAGESC, C++, JAVA ET

COMPARAISONDESLANGAGESC, C++, JAVA ET REPUBLIQUE DU BENIN *******@******* MINISTERE DE L ENSEIGNEMENT SUPERIEUR ET DE LA RECHERCHE SCIENTIFIQUE(MESRS) *******@******* UNIVERSITE D ABOMEY CALAVI(UAC) *******@******* ECOLE POLYTECHNIQUE D ABPOMEY

Plus en détail

Bases de programmation. Cours 5. Structurer les données

Bases de programmation. Cours 5. Structurer les données Bases de programmation. Cours 5. Structurer les données Pierre Boudes 1 er décembre 2014 This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. Types char et

Plus en détail

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr Mars 2002 Pour Irène et Marie Legal Notice Copyright c 2002 Patrick Cégielski Université

Plus en détail

Conventions d écriture et outils de mise au point

Conventions d écriture et outils de mise au point Logiciel de base Première année par alternance Responsable : Christophe Rippert Christophe.Rippert@Grenoble-INP.fr Introduction Conventions d écriture et outils de mise au point On va utiliser dans cette

Plus en détail

INF 321 : mémento de la syntaxe de Java

INF 321 : mémento de la syntaxe de Java INF 321 : mémento de la syntaxe de Java Table des matières 1 La structure générale d un programme 3 2 Les composants élémentaires de Java 3 2.1 Les identificateurs.................................. 3 2.2

Plus en détail

Plan du cours. Historique du langage http://www.oracle.com/technetwork/java/index.html. Nouveautés de Java 7

Plan du cours. Historique du langage http://www.oracle.com/technetwork/java/index.html. Nouveautés de Java 7 Université Lumière Lyon 2 Faculté de Sciences Economiques et Gestion KHARKIV National University of Economic Introduction au Langage Java Master Informatique 1 ère année Julien Velcin http://mediamining.univ-lyon2.fr/velcin

Plus en détail

Langage C. Patrick Corde. Patrick.Corde@idris.fr. 22 juin 2015. Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin 2015 1 / 289

Langage C. Patrick Corde. Patrick.Corde@idris.fr. 22 juin 2015. Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin 2015 1 / 289 Langage C Patrick Corde Patrick.Corde@idris.fr 22 juin 2015 Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin 2015 1 / 289 Table des matières I 1 Présentation du langage C Historique Intérêts

Plus en détail

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre 2009. Enrica.Duchi@liafa.jussieu.fr

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre 2009. Enrica.Duchi@liafa.jussieu.fr . Cours intensif Java 1er cours: de C à Java Septembre 2009 Enrica DUCHI LIAFA, Paris 7 Enrica.Duchi@liafa.jussieu.fr LANGAGES DE PROGRAMMATION Pour exécuter un algorithme sur un ordinateur il faut le

Plus en détail

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr Table des matières 1 Les bases 3 2 Variables et constantes 5 3 Quelques fonctions indispensables

Plus en détail

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile Dans ce TP, vous apprendrez à définir le type abstrait Pile, à le programmer en Java à l aide d une interface

Plus en détail

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java Langages objets Introduction M2 Pro CCI, Informatique Emmanuel Waller, LRI, Orsay présentation du module logistique 12 blocs de 4h + 1 bloc 2h = 50h 1h15 cours, 45mn exercices table, 2h TD machine page

Plus en détail

Programmation C++ (débutant)/instructions for, while et do...while

Programmation C++ (débutant)/instructions for, while et do...while Programmation C++ (débutant)/instructions for, while et do...while 1 Programmation C++ (débutant)/instructions for, while et do...while Le cours du chapitre 4 : le for, while et do...while La notion de

Plus en détail

Cours d initiation à la programmation en C++ Johann Cuenin

Cours d initiation à la programmation en C++ Johann Cuenin Cours d initiation à la programmation en C++ Johann Cuenin 11 octobre 2014 2 Table des matières 1 Introduction 5 2 Bases de la programmation en C++ 7 3 Les types composés 9 3.1 Les tableaux.............................

Plus en détail

Programmer en JAVA. par Tama (tama@via.ecp.fr( tama@via.ecp.fr)

Programmer en JAVA. par Tama (tama@via.ecp.fr( tama@via.ecp.fr) Programmer en JAVA par Tama (tama@via.ecp.fr( tama@via.ecp.fr) Plan 1. Présentation de Java 2. Les bases du langage 3. Concepts avancés 4. Documentation 5. Index des mots-clés 6. Les erreurs fréquentes

Plus en détail

Les chaînes de caractères

Les chaînes de caractères Les chaînes de caractères Dans un programme informatique, les chaînes de caractères servent à stocker les informations non numériques comme par exemple une liste de nom de personne ou des adresses. Il

Plus en détail

Langage Éric Guérin 5 octobre 2010

Langage Éric Guérin 5 octobre 2010 Langage Éric Guérin 5 octobre 2010 Langage C TABLE DES MATIÈRES Table des matières 1 Introduction 7 1.1 Historique........................................... 7 1.2 Architecture matérielle....................................

Plus en détail

Notions fondamentales du langage C# Version 1.0

Notions fondamentales du langage C# Version 1.0 Notions fondamentales du langage C# Version 1.0 Z 2 [Notions fondamentales du langage Csharp] [Date : 25/03/09] Sommaire 1 Tout ce qu il faut savoir pour bien commencer... 3 1.1 Qu est ce qu un langage

Plus en détail

Langage Java. Classe de première SI

Langage Java. Classe de première SI Langage Java Table des matières 1. Premiers pas...2 1.1. Introduction...2 1.2. Mon premier programme...2 1.3. Les commentaires...2 2. Les variables et les opérateurs...2 3. La classe Scanner...3 4. Les

Plus en détail

I. Introduction aux fonctions : les fonctions standards

I. Introduction aux fonctions : les fonctions standards Chapitre 3 : Les fonctions en C++ I. Introduction aux fonctions : les fonctions standards A. Notion de Fonction Imaginons que dans un programme, vous ayez besoin de calculer une racine carrée. Rappelons

Plus en détail

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1 Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1 B. Baert & F. Ludewig Bruno.Baert@ulg.ac.be - F.Ludewig@ulg.ac.be Qu est-ce que la programmation? Programmer Ecrire un

Plus en détail

Programmation C. J.-F. Lalande. 15 novembre 2012

Programmation C. J.-F. Lalande. 15 novembre 2012 Programmation C J.-F. Lalande novembre 0 Ce cours est mis à disposition par Jean-François Lalande selon les termes de la licence Creative Commons Attribution - Pas d Utilisation Commerciale - Partage à

Plus en détail

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51 DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51 PLAN DU COURS Introduction au langage C Notions de compilation Variables, types, constantes, tableaux, opérateurs Entrées sorties de base Structures de

Plus en détail

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40 Déroulement du cours Introduction Concepts Java Remarques Langage et Concepts de Programmation Orientée-Objet Gauthier Picard École Nationale Supérieure des Mines de Saint-Étienne gauthier.picard@emse.fr

Plus en détail

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

INTRODUCTION A JAVA. Fichier en langage machine Exécutable INTRODUCTION A JAVA JAVA est un langage orienté-objet pur. Il ressemble beaucoup à C++ au niveau de la syntaxe. En revanche, ces deux langages sont très différents dans leur structure (organisation du

Plus en détail

1.6- Génération de nombres aléatoires

1.6- Génération de nombres aléatoires 1.6- Génération de nombres aléatoires 1- Le générateur aléatoire disponible en C++ 2 Création d'un générateur aléatoire uniforme sur un intervalle 3- Génération de valeurs aléatoires selon une loi normale

Plus en détail

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars 2014. http://homepages.laas.fr/matthieu/cours/java/java.pdf

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars 2014. http://homepages.laas.fr/matthieu/cours/java/java.pdf Introduction à Java Matthieu Herrb CNRS-LAAS http://homepages.laas.fr/matthieu/cours/java/java.pdf Mars 2014 Plan 1 Concepts 2 Éléments du langage 3 Classes et objets 4 Packages 2/28 Histoire et motivations

Plus en détail

TP 1. Prise en main du langage Python

TP 1. Prise en main du langage Python TP. Prise en main du langage Python Cette année nous travaillerons avec le langage Python version 3. ; nous utiliserons l environnement de développement IDLE. Étape 0. Dans votre espace personnel, créer

Plus en détail

Programmation en C - Sommaire

Programmation en C - Sommaire Programmation en C - Sommaire PROGRAMMATION EN C - SOMMAIRE... 1 CHAPITRE 0 : INTRODUCTION :... 5 I) NOTATIONS ET SYMBOLES :... 5 II) C, LA NAISSANCE D'UN LANGAGE DE PROGRAMMATION PORTABLE... :... 6 1)

Plus en détail

Chap III : Les tableaux

Chap III : Les tableaux Chap III : Les tableaux Dans cette partie, on va étudier quelques structures de données de base tels que : Les tableaux (vecteur et matrice) Les chaînes de caractères LA STRUCTURE DE TABLEAU Introduction

Plus en détail

Le langage C. Introduction, guide de reference

Le langage C. Introduction, guide de reference Le langage C Introduction, guide de reference Ce document est une présentation du langage de programmation C, de sa syntaxe et de ses spécificités. Il est destiné essentiellement à servir de mémo-guide

Plus en détail

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère L'héritage et le polymorphisme en Java Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère En java, toutes les classes sont dérivée de la

Plus en détail

Généralités sur le Langage Java et éléments syntaxiques.

Généralités sur le Langage Java et éléments syntaxiques. Généralités sur le Langage Java et éléments syntaxiques. Généralités sur le Langage Java et éléments syntaxiques....1 Introduction...1 Genéralité sur le langage Java....1 Syntaxe de base du Langage...

Plus en détail

Notes du cours 4M056 Programmation en C et C++ Vincent Lemaire et Damien Simon

Notes du cours 4M056 Programmation en C et C++ Vincent Lemaire et Damien Simon Notes du cours 4M056 Programmation en C et C++ Vincent Lemaire et Damien Simon 13 janvier 2015 2 Table des matières Organisation générale du cours 7 1 Notions générales d algorithmique et de programmation

Plus en détail

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation : Algorithmique et programmation : STRUCTURES DE DONNÉES A. Structure et enregistrement 1) Définition et rôle des structures de données en programmation 1.1) Définition : En informatique, une structure de

Plus en détail

Initiation à la programmation en Python

Initiation à la programmation en Python I-Conventions Initiation à la programmation en Python Nom : Prénom : Une commande Python sera écrite en caractère gras. Exemples : print 'Bonjour' max=input("nombre maximum autorisé :") Le résultat de

Plus en détail

Rappels Entrées -Sorties

Rappels Entrées -Sorties Fonctions printf et scanf Syntaxe: écriture, organisation Comportement Données hétérogènes? Gestion des erreurs des utilisateurs 17/11/2013 Cours du Langage C ibr_guelzim@yahoo.fr ibrahimguelzim.atspace.co.uk

Plus en détail

INITIATION A LA PROGRAMMATION

INITIATION A LA PROGRAMMATION 2004-2005 Université Paris Dauphine IUP Génie Mathématique et Informatique INITIATION A LA PROGRAMMATION PROCEDURALE, A L'ALGORITHMIQUE ET AUX STRUCTURES DE DONNEES PAR LE LANGAGE C Maude Manouvrier La

Plus en détail

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie Chapitre I : Les bases du C++ Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie du logiciel, et ce depuis

Plus en détail

Les structures. Chapitre 3

Les structures. Chapitre 3 Chapitre 3 Les structures Nous continuons notre étude des structures de données qui sont prédéfinies dans la plupart des langages informatiques. La structure de tableau permet de regrouper un certain nombre

Plus en détail

STAGE IREM 0- Premiers pas en Python

STAGE IREM 0- Premiers pas en Python Université de Bordeaux 16-18 Février 2014/2015 STAGE IREM 0- Premiers pas en Python IREM de Bordeaux Affectation et expressions Le langage python permet tout d abord de faire des calculs. On peut évaluer

Plus en détail

Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS Sommaire

Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS Sommaire Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS CCS Sommaire Généralités sur le langage. 2 Structure d un programme en C.. 3 Les constantes et équivalences.. 4 Les variables...

Plus en détail

Java Licence Professionnelle CISII, 2009-10

Java Licence Professionnelle CISII, 2009-10 Java Licence Professionnelle CISII, 2009-10 Cours 4 : Programmation structurée (c) http://www.loria.fr/~tabbone/cours.html 1 Principe - Les méthodes sont structurées en blocs par les structures de la programmation

Plus en détail

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004 Questionnaire d'examen final INF1101 Sigle du cours Nom : Signature : Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004 Professeur(s)

Plus en détail

Présentation du langage et premières fonctions

Présentation du langage et premières fonctions 1 Présentation de l interface logicielle Si les langages de haut niveau sont nombreux, nous allons travaillé cette année avec le langage Python, un langage de programmation très en vue sur internet en

Plus en détail

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE QCM Remarque : - A une question correspond au moins 1 réponse juste - Cocher la ou les bonnes réponses Barème : - Une bonne réponse = +1 - Pas de réponse = 0

Plus en détail

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier Cours de C Petits secrets du C & programmation avancée Sébastien Paumier paumier@univ-mlv.fr Illustrations provenant du site http://tux.crystalxp.net/ 1 Affectations étendues a+=expression a=a+expression

Plus en détail

Cours Informatique Master STEP

Cours Informatique Master STEP Cours Informatique Master STEP Bases de la programmation: Compilateurs/logiciels Algorithmique et structure d'un programme Programmation en langage structuré (Fortran 90) Variables, expressions, instructions

Plus en détail

Informatique Générale

Informatique Générale Informatique Générale Guillaume Hutzler Laboratoire IBISC (Informatique Biologie Intégrative et Systèmes Complexes) guillaume.hutzler@ibisc.univ-evry.fr Cours Dokeos 625 http://www.ens.univ-evry.fr/modx/dokeos.html

Plus en détail

Programme Compte bancaire (code)

Programme Compte bancaire (code) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; Programme Compte bancaire (code) namespace compte_bancaire /// Classe Program public

Plus en détail

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy Claude Delannoy Programmer en langage C++ 8 e édition Avec une intro aux design patterns et une annexe sur la norme C++11 Groupe Eyrolles, 1993-2011. Groupe Eyrolles, 2014, pour la nouvelle présentation,

Plus en détail

Algorithmes et Programmes. Introduction à l informatiquel. Cycle de vie d'un programme (d'un logiciel) Cycle de vie d'un programme (d'un logiciel)

Algorithmes et Programmes. Introduction à l informatiquel. Cycle de vie d'un programme (d'un logiciel) Cycle de vie d'un programme (d'un logiciel) Algorithmes et Programmes Introduction à l informatiquel! Vie d'un programme! Algorithme! Programmation : le langage! Exécution et test des programmes Chapitre : Algorithmes et Programmes 2 Cycle de vie

Plus en détail

Programmation en C/C++

Programmation en C/C++ INSA de Lyon Département Génie Electrique Module IF1,IF3,IF4 Programmation en C/C++ Thomas Grenier Nicolas Ducros Tanneguy Redarce Lyon, le 3 mars 2015 2 / 63 Table des matières 1 Développement en C++

Plus en détail

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if Pierre Boudes 28 septembre 2011 This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike

Plus en détail

Support de Cours de Langage C. Christian Bac

Support de Cours de Langage C. Christian Bac Support de Cours de Langage C Christian Bac 15 février 2013 ii Table des matières Avant-propos xi 1 Historique et présentation 1 1.1 Historique........................................... 1 1.2 Présentation

Plus en détail

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme Rappel Ralf Treinen Université Paris Diderot UFR Informatique Laboratoire Preuves, Programmes et Systèmes treinen@pps.univ-paris-diderot.fr 6 mai 2015 Jusqu'à maintenant : un petit langage de programmation

Plus en détail

Le Langage C++ Patrick TRAU - ULP IPST version du 02/10/05

Le Langage C++ Patrick TRAU - ULP IPST version du 02/10/05 Le Langage C++ Patrick TRAU - ULP IPST version du 02/10/05 1) Introduction 1.1) Organisation - fonctionnement de l'ordinateur Je suppose que vous savez utiliser un ordinateur, et comprenez comment il fonctionne.

Plus en détail

Anis ASSÈS Mejdi BLAGHGI Mohamed Hédi ElHajjej Mohamed Salah Karouia

Anis ASSÈS Mejdi BLAGHGI Mohamed Hédi ElHajjej Mohamed Salah Karouia Ministère de l Enseignement Supérieur, de la Recherche Scientifique et de la Technologie Direction Générale des Etudes Technologiques Institut Supérieur des Etudes Technologiques de Djerba SUPPORT DE COURS

Plus en détail

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles) 1/4 Objectif de ce cours /4 Objectifs de ce cours Introduction au langage C - Cours Girardot/Roelens Septembre 013 Du problème au programme I passer d un problème exprimé en français à la réalisation d

Plus en détail

et Programmation Objet

et Programmation Objet FACULTE POLYTECHNIQUE DE MONS Service d Informatique et Programmation Objet Mohammed Benjelloun 2 ème Bachelier Année académique 2008-2009 Table des matières Avant-propos--------------------------------------------------------------------------

Plus en détail

1. Qu'est-ce que SQL?... 2. 2. La maintenance des bases de données... 2. 3. Les manipulations des bases de données... 5

1. Qu'est-ce que SQL?... 2. 2. La maintenance des bases de données... 2. 3. Les manipulations des bases de données... 5 1. Qu'est-ce que SQL?... 2 2. La maintenance des bases de données... 2 2.1 La commande CREATE TABLE... 3 2.2 La commande ALTER TABLE... 4 2.3 La commande CREATE INDEX... 4 3. Les manipulations des bases

Plus en détail

Introduction au C++ et à la programmation objet

Introduction au C++ et à la programmation objet Introduction au C++ et à la programmation objet Version 1.12b (Mars 2013) par Emmanuel Courcelle emmanuel.courcelle@toulouse.inra.fr 1 Cours C++ - Emmanuel Courcelle / CUTIS / Formation permanente du C.N.R.S.

Plus en détail

Travaux pratiques. Compression en codage de Huffman. 1.3. Organisation d un projet de programmation

Travaux pratiques. Compression en codage de Huffman. 1.3. Organisation d un projet de programmation Université de Savoie Module ETRS711 Travaux pratiques Compression en codage de Huffman 1. Organisation du projet 1.1. Objectifs Le but de ce projet est d'écrire un programme permettant de compresser des

Plus en détail

Algorithme. Table des matières

Algorithme. Table des matières 1 Algorithme Table des matières 1 Codage 2 1.1 Système binaire.............................. 2 1.2 La numérotation de position en base décimale............ 2 1.3 La numérotation de position en base binaire..............

Plus en détail

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C Haute Ecole d Ingénierie et de Gestion Du Canton du Vaud MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C Programmation en mode simulation 1. DOCUMENTS DE RÉFÉRENCE...

Plus en détail

Méthodes de programmation systèmes UE n NSY103. Notes de cours. Nombre d'heures : 55h (~18 + 1 cours de 3 heures)

Méthodes de programmation systèmes UE n NSY103. Notes de cours. Nombre d'heures : 55h (~18 + 1 cours de 3 heures) Méthodes de programmation systèmes UE n NSY103 Notes de cours Code de l UE : NSY103 Titre de la formation : Méthodes de programmation systèmes Ouvert : Ouvert Type de diplôme : Unité de valeur CNAM. Nombre

Plus en détail

as Architecture des Systèmes d Information

as Architecture des Systèmes d Information Plan Plan Programmation - Introduction - Nicolas Malandain March 14, 2005 Introduction à Java 1 Introduction Présentation Caractéristiques Le langage Java 2 Types et Variables Types simples Types complexes

Plus en détail

Recherche dans un tableau

Recherche dans un tableau Chapitre 3 Recherche dans un tableau 3.1 Introduction 3.1.1 Tranche On appelle tranche de tableau, la donnée d'un tableau t et de deux indices a et b. On note cette tranche t.(a..b). Exemple 3.1 : 3 6

Plus en détail

Le Langage C Licence Professionnelle Qualité Logiciel Pr. Mouad BEN MAMOUN ben_mamoun@fsr.ac.ma Année universitaire 2011/2012

Le Langage C Licence Professionnelle Qualité Logiciel Pr. Mouad BEN MAMOUN ben_mamoun@fsr.ac.ma Année universitaire 2011/2012 Le Langage C Licence Professionnelle Qualité Logiciel Pr. Mouad BEN MAMOUN ben_mamoun@fsr.ac.ma Année universitaire 2011/2012 2011/2012 Pr. Ben Mamoun 1 Plan du cours (1) 1. Introduction 2. Types, opérateurs

Plus en détail

Algorithmique et programmation : les bases (VBA) Corrigé

Algorithmique et programmation : les bases (VBA) Corrigé PAD INPT ALGORITHMIQUE ET PROGRAMMATION 1 Cours VBA, Semaine 1 mai juin 2006 Corrigé Résumé Ce document décrit l écriture dans le langage VBA des éléments vus en algorithmique. Table des matières 1 Pourquoi

Plus en détail

Programmation en Java IUT GEII (MC-II1) 1

Programmation en Java IUT GEII (MC-II1) 1 Programmation en Java IUT GEII (MC-II1) 1 Christophe BLANC - Paul CHECCHIN IUT Montluçon Université Blaise Pascal Novembre 2009 Christophe BLANC - Paul CHECCHIN Programmation en Java IUT GEII (MC-II1)

Plus en détail

LES TYPES DE DONNÉES DU LANGAGE PASCAL

LES TYPES DE DONNÉES DU LANGAGE PASCAL LES TYPES DE DONNÉES DU LANGAGE PASCAL 75 LES TYPES DE DONNÉES DU LANGAGE PASCAL CHAPITRE 4 OBJECTIFS PRÉSENTER LES NOTIONS D ÉTIQUETTE, DE CONS- TANTE ET DE IABLE DANS LE CONTEXTE DU LAN- GAGE PASCAL.

Plus en détail

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu. Seance 2: Complétion du code de jeu. (durée max: 2h) Mot clé const et pointeurs: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu. Implémentez jeu_recupere_piece

Plus en détail

Algorithmique, Structures de données et langage C

Algorithmique, Structures de données et langage C UNIVERSITE PAUL SABATIER TOULOUSE III Algorithmique, Structures de données et langage C L3 IUP AISEM/ICM Janvier 2005 J.M. ENJALBERT Chapitre 1 Rappels et compléments de C 1.1 Structures Une structure

Plus en détail

ALGORITHMIQUE ET PROGRAMMATION En C

ALGORITHMIQUE ET PROGRAMMATION En C Objectifs ALGORITHMIQUE ET PROGRAMMATION Une façon de raisonner Automatiser la résolution de problèmes Maîtriser les concepts de l algorithmique Pas faire des spécialistes d un langage Pierre TELLIER 2

Plus en détail

Programmation système I Les entrées/sorties

Programmation système I Les entrées/sorties Programmation système I Les entrées/sorties DUT 1 re année Université de Marne La vallée Les entrées-sorties : E/O Entrées/Sorties : Opérations d échanges d informations dans un système informatique. Les

Plus en détail

REPUBLIQUE ALGERIENNE DEMOCRATIQUE ET POPULAIRE UNIVERSITE M HAMED BOGARA DE BOUMERDES

REPUBLIQUE ALGERIENNE DEMOCRATIQUE ET POPULAIRE UNIVERSITE M HAMED BOGARA DE BOUMERDES REPUBLIQUE ALGERIENNE DEMOCRATIQUE ET POPULAIRE MINISTERE DE L ENSEIGNEMENT SUPERIEUR ET DE LA RECHERCHE SCIENTIFIQUE UNIVERSITE M HAMED BOGARA DE BOUMERDES FACULTE DES SCIENCES - DEPARTEMENT PHYSIQUE

Plus en détail

BTS IRIS Cours et Travaux Pratiques. Programmation C. A. Lebret, TSIRIS, Lycée Diderot, 1995/06. en conformité avec le référentiel du BTS IRIS

BTS IRIS Cours et Travaux Pratiques. Programmation C. A. Lebret, TSIRIS, Lycée Diderot, 1995/06. en conformité avec le référentiel du BTS IRIS BTS IRIS Cours et Travaux Pratiques Programmation C A. Lebret, TSIRIS, Lycée Diderot, 1995/06 en conformité avec le référentiel du BTS IRIS Activité Codage et Réalisation Tâches T3.3, T3.4 et T3.5 Temps

Plus en détail

Département Automatisation et Informatisation Année 2005-2006. Programmation en C++ Institut des Sciences et Techniques de l Ingénieur d Angers

Département Automatisation et Informatisation Année 2005-2006. Programmation en C++ Institut des Sciences et Techniques de l Ingénieur d Angers Département Automatisation et Informatisation Année 2005-2006 Programmation en C++ Institut des Sciences et Techniques de l Ingénieur d Angers 1 Bertrand Cottenceau 1. Introduction du cours de C++...3

Plus en détail

TP : Gestion d une image au format PGM

TP : Gestion d une image au format PGM TP : Gestion d une image au format PGM Objectif : L objectif du sujet est de créer une classe de manipulation d images au format PGM (Portable GreyMap), et de programmer des opérations relativement simples

Plus en détail

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions Cours d introduction à l informatique Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions Qu est-ce qu un Une recette de cuisine algorithme? Protocole expérimental

Plus en détail

Java Licence Professionnelle CISII, 2009-2010. Cours 2 : Classes et Objets

Java Licence Professionnelle CISII, 2009-2010. Cours 2 : Classes et Objets Licence Professionnelle CISII, 2009-2010 Cours 2 : Classes et Objets 1 Classes et Objets Objectifs des LOO : - Manipuler des objets - Découper les programmes suivant les types des objets manipulés - Regrouper

Plus en détail