Bases du langage C++ Syntaxe * Dans cette partie, uniquement les aspects procéduraux * Aspects objet vus en deuxième partie * Syntaxe similaire au C * Instructions terminées par ";" * Commentaires * "//" pour une seule ligne * "/*...*/" pour plusieurs lignes * Opérateurs identiques * Structures de contrôle identiques * Sensible à la casse * Variables fortement typées Variables * Toujours préciser le type à la déclaration * type nom_variable; * Ensuite, le type de la variable ne peut plus changer * Intérêt: contrôle tout au long du code, ce qui empêche les erreurs * Possibilité de fournir une valeur initiale * type nom_variable = valeur; * Toujours déclarer une variable * Variable globale * Paramètre de fonction * Variable locale * Déclarer une constante: mot-clé "const" * const int a = 12; Types élémentaires (1/2) * Entier: [ signed / unsigned ] short / int / long * Domaine de valeurs dépendant de l'architecture matérielle * Par exemple, sur un Intel 32 bits * short ==> 16 bits / 2 octets * int ==> 32 bits / 4 octets * long ==> 64 bits / 8 octets * Entier signé par défaut * Signé = peut prendre une valeur négative * int x ? signed int x ==> nombre entier pouvant être négatif * unsigned int x ==> nombre entier positif Types élémentaires (2/2) * Caractère: [ signed / unsigned ] char * Valeur délimitée par le symbole "'" * char x = 'a'; * Equivalent à un nombre * Code ASCII / 1 octet * Exemple: 'a' ? 97 * Flottant: float / double * double ==> plus de précision, mais plus de place en mémoire Conversion de type * Possibilité de convertir une valeur d'un type à un autre * Si la procédure est prévue en standard * Ou si la procédure a été définie par le développeur * Surcharge d'opérateur * Opérateur de conversion * Conversion implicite * Quelques conversions sont évidentes * int x = 5; double y = x; * Conversion explicite ==> opérateur "(type)" * Comme le contrôle des types doit être garanti * La plupart des conversions sont interdites implicitement * double y = 2.5; int x = (int)y; Portée des variables * Portée limitée au bloc d'instructions (entre "{" et "}") * Que ce soit une fonction, une boucle, une condition... * Exemple int x = ...; if (x == 3) { int y = 2; } cout << y; ==> erreur * Variable détruite à la sortie du bloc Opérateurs classiques * Arithmétique: +, -, *, /, % (modulo) * Incrémentation / décrémentation: --, ++ * i++ / ++i ? i = i+1 * i-- / --i ? i = i-1 * Affectation: =, +=, -=, *=, /=, %= * i += 3 ? i = i+3 * Logique: && (et), || (ou), ! (non) * Comparaison: ==, <, >, <=, >=, != Structures de contrôle * Bloc d'instructions délimité par "{" et "}" * Facultatif si une seule ligne * if (x == 1) y = 2; ? if (x == 1) { y = 2; } * Structures conditionnelles * if (test1) { action1 } else if (test2) { action2 } else { action3 } * switch (variable) { case valeur1: action1 break; case valeur2: action2 break; default: action3 } * Structures de boucle * while (test) { action } * do { action } while (test); * for (depart; test; suivant) { action } Tableaux * Déclaration (et création) d'un tableau * type nom_tableau[taille]; * Possibilité de remplir le tableau à la déclaration * type nom_tableau[] = { valeur_1,valeur_2,... }; * Accès (en lecture ou écriture) à un élément * A l'aide de son indice i: nom_tableau[i] * Eléments numérotés à partir de 0 * Déclaration (sans création) d'un tableau * type * nom_tableau; * Voir les pointeurs * "Tableau constant" = valeur constante des éléments * const type * nom_tableau; * const type nom_tableau[taille]; Chaînes de caractères * Chaîne de caractères = tableau de caractères * char nom[] = "Bruno"; * Mais un caractère spécial (code ASCII = 0) termine le tableau * Le tableau "nom" contient 6 caractères * char nom[] = { 'B', 'r', 'u', 'n', 'o', 0 }; * Autre représentation en C++: le type "string" * string nom = "Bruno"; * Opérateur de concaténation: nom = nom + " Nawouak"; * Taille d'une chaîne: unsigned n = nom.length(); * Tableau de caractères: const char * tab = nom.c_str(); Bibliothèque standard * De nombreuses fonctionnalités fournies en standard * Types, fonctions, variables globales, constantes... * Pour les utiliser * Inclure l'entête contenant la fonctionnalité * Voir la documentation * Pour les chaînes de caractères * #include <string> * Fonctionnalité précédée du préfixe "std::" * Exemple: std::string * Pour éviter d'écrire le préfixe dans un bloc * using namespace std; Flux d'entrée/sortie * Entête: #include <iostream> * Sortie console = flux = variable globale "cout" * cout << x; ==> affiche le contenu de "x" sur la console * cout << endl; ==> retour à la ligne * Possibilité d'enchaîner: cout << x << endl; * Entrée console = flux = variable globale "cin" * cin >> x; ==> récupère l'entier saisi dans "x" * Fichier = flux * Entête: #include <fstream> * Fichier d'entrée: ifstream * Fichier de sortie: ofstream Manipuler une chaîne comme un flux * Entête: #include <sstream> * Ecriture dans un flux "stringstream" stringstream ss; ss << 10 << '/' << 9 << '/' << 2012; string date = ss.str(); ==> récupération de la chaîne * Lecture d'un flux chaîne stringstream ss; ss << "3 7 13 27"; int x; int somme = 0; for (unsigned i = 0; i < 4; ++i) { ss >> x; somme += x; } Fonctions (1/2) * Permettent de factoriser / réutiliser du code * Portions de code associées à un nom * Reçoivent des arguments en entrée * Retournent éventuellement une valeur en sortie * type_retour nom(arguments) { action; return resultat; } * Pas de retour: type_retour = void * Exemple int ajouter(int a,int b) { int c = a + b; return c; } Fonctions (2/2) * Passage par valeur / copie * int f(int x) * L'argument "x" est une copie * Modification limitée à "f" * int ajouter1(int a,int b) { return (a + b); } * w = ajouter1(u,v); * Passage par référence * int f(int & x) * L'argument "x" est un alias * Modification répercutée hors de "f" * void ajouter2(int a,int b, int & c) { c = a + b; } * ajouter2(u,v,w); Organisation de la mémoire * Variable = alias d'une zone mémoire allouée pour stocker des données d'un type défini * int x; ==> zone mémoire étiquetée "x" pour stocker un entier * Programme = deux zones pour stocker des données * La pile * Mémoire pour les variables locales (et les arguments de fonctions) * Allocation mémoire automatique à partir de la déclaration * A chaque appel de fonction, les variables locales sont empilées * A la fin de la fonction, ces variables sont dépilées * Le tas * Mémoire préservée durant toute la durée du programme * Pas d'organisation prédéfinie des zones allouées * La mémoire allouée dans le tas survit après la fonction qui l'a créée Allocation mémoire * Pour créer une zone mémoire sur le tas: instruction "new" * new int ==> création d'un entier * new int[10] ==> création d'un tableau de 10 entiers * "new" retourne l'adresse mémoire de la zone allouée ==> le "pointeur" * Déclaration d'un pointeur: type * nom_pointeur; * int * px = new int; * int * px = new int[10]; * Libérer une zone mémoire * Elément simple: delete px; * Tableau d'éléments: delete [] px; Accès à la mémoire * Accès à la valeur référencée par un pointeur: opérateur "*" * *px ==> valeur entière référencée par "px" * int j = *px; ==> OK * int j = px; ==> non, car "px" est un pointeur * Obtenir l'adresse d'une variable: opérateur "&" * int i = 5; * int * px = &i; * *px = 12; Exemple: les deux mémoires void f(void) { int x = 3; int y = 7; int * px = new int; *px = 13; } Arithmétique des pointeurs (1/2) * Un tableau est représenté par un pointeur * int tab1[] = { 1,2,3,4,5 }; * int * tab2 = tab1; * Différence: "tab1" est un pointeur constant * Arithmétique * *tab2 ==> valeur entière pointée par "tab2" * Equivalent à "tab2[0]" * De manière générale: tab2[i] ? *(tab2+i) * tab2+i = adresse de "tab2" décalée "i" fois * = de la taille en octets d'un élément * sizeof(type) = taille en octets d'un type de données Arithmétique des pointeurs (2/2) int tab[] = { 3,5,7,13,27 }; int * px; |