Debuter Avec C
Debuter Avec C
Debuter Avec C
Historique du C et du C++
[Deitel et Deitel, Comment Programmez en C++. Eyrolles, 2ième édition, 2000, Section
1.7, pp. 9-10]
" Le C++ a été développé à partir du C qui fut lui-même élaboré à partir de deux
langages de programmation antérieurs, le BCPL et le B. Le BCPL fut développé
en 1967 par Martin Richards comme langage d’écriture de logiciels de systèmes
d’exploitation et de compilateurs. Ken Thompson modela plusieurs particularités
de son langage B à partir de leurs équivalents en BCPL. En 1970, il utilisa le
langage B pour créer des versions primitives du système d’exploitation UNIX aux
laboratoires Bell sur un ordinateur DEC PDP-7. Le BCPL et le B étaient des
langages « non typés »; chaque élément de données occupait un « mot » en
mémoire et le fardeau de traiter un élément comme un nombre entier ou comme
un nombre réel, par exemple, incombait au programmeur.
À la fin des années 1970, le C avait évolué en ce qu’on désigne maintenant par les
vocables de « C conventionnel », « C classique » ou « C de Kernighan et
Ritchie ». En 1978, la publication chez Prentice-Hall du livre The C Programming
Language de Kernighan and Ritchie attira l’attention générale sur ce langage.
-1-
l’échelle mondiale; le document collectif du standard fut publié en 1990 et porte
l’identification ANSI/ISO 9899 : 1990. On peut commander des copies de ce
document auprès de l’ANSI. La deuxième édition du Kernighan et Ritchie,
publiée en 1988, est conforme à cette version appelée ANSI C.
Le C++, une extension du C, a été développé au début des années 1980 par Bjarne
Stroustrup aux laboratoires Bell. Le C++ procure une quantité de fonctionnalités
qui rehaussent le langage C et, de surcroît, offre des possibilités pour la
programmation orientée objets."
.cpp Fichier source. Ces fichiers textes contiennent le code des programmes.
Les fichiers d’entête système de certains vieux compilateurs possèdent une extension .h,
par exemple :
#include <iostream.h>
Ajouter simplement un .h ne fonctionne toutefois pas pour tous les fichiers inclus. Par
exemple, en C++ standard, vous pouvez inclure la directive #include <string> ; la
-2-
directive #include <string.h> n’inclut pas les chaînes C++, mais les chaînes de style C,
totalement différentes et moins utiles.
Un autre fichier d’entête courant contient des fonctions mathématiques. En C++ standard,
vous employez la directive #include <cmath>. Avec des compilateurs plus anciens, vous
employez à la place #include <math.h>.
Les anciens compilateurs ne prennent pas en charge les espaces de noms. Dans ce cas,
omettez la directive using namespace std;
Différences :
-3-
Mots-clés C et C++
-4-
Fonctions
La bibliothèque standard du C++ offre une riche collection de fonctions pour effectuer les
calculs mathématiques courants, les manipulations de chaînes de caractères, les entrées et
les sorties, la vérification des erreurs, etc. Ces fonctions font partie intégrante de
l’environnement de programmation du C++. Leur emploi accroît la portabilité des
programmes; de plus, il est difficile d’améliorer leur performance.
Chaque fonction devrait se limiter à effectuer une tâche unique et bien définie. Le nom de
la fonction devrait exprimer cette tâche avec clarté.
type_de_valeur_renvoyée Nom_de_la_fonction
( type_de_x argument_x, ……
type_de_z argument_z)
{ déclarations et instructions formant le corps de la fonction (bloc) }
Note : (i) C++ n’impose pas de récupérer la valeur retournée par une fonction.
(ii) Si la fonction ne possède pas de paramètre, C++ n’indique rien entre les
parenthèses ou le mot clé void. Une liste de paramètres de fonction vide en
-5-
C++ a une signification tout à fait différente d’une telle liste en C. En C,
elle signifie que la vérification des arguments est désactivée; autrement
dit, l’appel de fonction peut passer les arguments qu’il veut. En C++, elle
signifie que la fonction ne prend aucun argument. Les programmes en C
utilisant cette caractéristique pourraient donc signaler des erreurs de
syntaxe lors de leur compilation en C++.
Exemple :
#include <iostream.h>
// Définition de la fonction
int cube(int m)
{
return m * m * m;
}
int main()
{
for (int i = 1; i <= 10; i++)
cout << cube(i) << “ “;
cout << endl;
return 0;
}
L’une des caractéristiques les plus importantes du C++ est le prototype de fonction. Cela
indique au compilateur le nom de la fonction, le type de données renvoyé par la fonction,
le nombre de paramètres que la fonction s’attend à recevoir, les types des paramètres et
l’ordre dans lequel ces paramètres devraient se suivre. Le compilateur utilise les
prototypes de fonctions pour valider les appels de fonction. Ils sont requis en C++; vous
pouvez utiliser les directives de précompilateur #include pour obtenir des prototypes de
fonctions de la bibliothèque standard ou des prototypes de fonctions personnelles à partir
de fichiers d’en-tête. Comme nous l’avons vu précédemment, un prototype de fonction
n’est pas requis si la définition de la fonction apparaît avant la première utilisation de
cette fonction; le cas échéant, la définition de la fonction sert également de prototype de
fonction.
Exemple :
#include <iostream.h>
-6-
int main()
{
for (int i = 1; i <= 10; i++)
cout << cube(i) << “ “;
cout << endl;
return 0;
}
// Définition de la fonction
int cube(int m)
{
return m * m * m;
}
En plus de fournir au compilateur les caractéristiques d’une fonction, cela donne aussi
l’occasion de donner la spécification d’une fonction.
Exemple :
float Racine_carree(float x);
Fichiers d’en-tête
Renferment :
- d’autres fichiers d’en-tête,
- les prototypes des fonctions
- la déclaration de variables externes
-7-
- des types de données
- les déclarations de structures,
- les déclarations de classes.
Précompilateur C++
-8-
Vehicule
Programme
d’application
-9-
Diriger le flux de données vers l’objet du flux de sortie standard
cout normalement associé à l’écran
Séquence de Description
changement de code
\n Nouvelle ligne. Positionne le curseur au début de la
ligne suivante.
\t Tabulation horizontale. Déplace le curseur à la
tabulation suivante.
\r Retour de chariot. Positionne le curseur au début de la
ligne courante; ne passe pas à la ligne suivante.
\a Alerte. Active la sonnerie du système.
\\ Barre oblique inverse. Utilisée pour afficher un
caractère de barre oblique inverse.
\" Guillemets. Sert à afficher un caractère de guillemets.
endl est un manipulateur de flux; il produit une nouvelle ligne, puis vide le tampon de
sortie. endl force donc toute sortie accumulée à s’afficher immédiatement.
Dans l’exemple précédent, on illustre aussi l’emploi de multiples opérateurs << dans une
seule instruction. La concaténation de flux est possible; il n’est pas nécessaire d’utiliser
des instructions de sortie multiples pour produire plusieurs parties de données.
- 10 -
Variables et opérateurs
float pi = 3.14159;
int jour = 21, mois = 9, annee;
- 11 -
Opérateur sizeof :
Permet d’obtenir l’espace occupé par une variable ou un type de donnée (octet).
Ex. : short i = 2;
cout << sizeof(i);
cout << sizeof(long);
La portée d’un identificateur est l’endroit où l’on peut référencer l’identificateur dans un
programme. Certains identificateurs peuvent être référencés dans la totalité d’un
programme; d’autres ne peuvent l’être que dans certaines parties d’un programme. Un
autre attribut associé à un identificateur est la période durant laquelle l’identificateur
existe en mémoire.
Variables locales
Ces variables sont créées lors de l’entrée du bloc dans lequel elles sont déclarées et
détruites lors de la sortie du bloc. Ces variables sont utilisables dans la portée où elles
sont définies i.e. à l’intérieur du bloc ou de la fonction où elles sont déclarées; elles sont
détruites lorsqu’on sort de sa portée.
En C++, contrairement à C, ce n’est plus nécessaire de définir les variables locales en tête
de bloc.
int cube(int m)
{
return m * m * m;
}
- 12 -
Note : Le mot-clé auto déclare explicitement des variables locales qui n’existent que
dans le corps de la fonction dans laquelle la définition apparaît. Les variables
locales ont, par défaut, cette propriété; c’est pourquoi, le mot clé auto est
rarement utilisé.
Arguments de fonction :
Variable registre :
Variable statique :
- Peut être utilisé pour connaître le nombre de fois où vous appelez une
fonction (compteur de fonction).
Variables globales
- 13 -
- portée : le fichier source où elles sont déclarées.
- Seules les fonctions qui sont définies après cette variable pourront
l’utiliser.
- La mise à jour des variables globales doit se faire avec des méthodes bien
spécifiées.
int cube(int m)
{
return m * m * m;
}
- Par défaut, les variables globales et les noms de fonctions ont l’attribut extern.
- Manipulables par toutes les fonctions définies dans le même fichier source à la suite
de leurs déclarations ou définitions dans le fichier.
- Puisqu’un projet peut contenir plusieurs sources, le mot clé extern est utilisé quand
une même variable est partagée par plusieurs fichiers d’un même projet.
- 14 -
Ex. : float x; fichier gestion.cpp
extern float x; fichier Application_gestion.cpp
Conversion de types
- Conversion implicite
- Conversion explicite
- 15 -
Définition des constantes symboliques
#define PI = 3.14159;
données typées
0 1 2 3
Ces constantes sont considérées comme des entiers (int) par le compilateur.
Structures de contrôle
Le C++ n’a que sept types différents de structures de contrôle : la séquence, 3 types de
sélection (if, if-else, switch) et 3 types de répétition (while, do / while, for), combinées de
seulement deux façons : par empilement ou par imbrication des structures de contrôle.
- 16 -
Tableaux
Rappel :
Ex. :
float tache[Max_elements];
- Les crochets utilisés pour l’indice d’un tableau sont en réalité un opérateur
du C++.
Ex. : int n[10] = {0}; // les éléments restants autres que n[0] sont
// initialisés à 0 par défaut.
- 17 -
Les tableaux déclarés static sont initialisés lors du chargement du
programme. Si le programmeur n’initialise pas explicitement un tableau de
type static, le compilateur l’initialisera à zéro. Toutefois, les éléments du
tableau local de type static d’une fonction ne sont pas initialisés à chaque
appel de la fonction; ils conservent leurs anciennes valeurs.
Voici un exemple :
...
Il peut arriver qu’une fonction ne doivent pas être autorisée à modifier les éléments d’un
tableau dans vos programmes. Le C++ offre le qualificatif de type const pour y arriver.
En effet, lorsque le qualificatif const précède le paramètre d’un tableau, les éléments de
ce dernier deviennent constants dans le corps de la fonction courante.
int main()
{
int a[] = {10, 20, 30};
essai(a) ;
...
}
void essai(const int b[])
{
b[0] = 2 ; // erreur
...
}
- 18 -
Chaînes de caractères
Note : Chaque fois que vous avez besoin de passer une chaîne de caractères à une
fonction, vous devez passer le nom du tableau.
- 19 -
(B) utilisation des fonctions de manipulation de chaînes
#include <iostream.h>
#include <string.h>
int main()
{
char Nom[20+1];
char Prenom[20+1];
Nom[7] = "\0";
cout << Nom; // Donne à l’affichage Boivin
Nom[7] = "-";
cout << Nom; // Donne à l’affichage Boivin – Leduc
// L’usage de \0 n’écrase pas les caractères suivants.
Comparer 2 chaînes
- 20 -
Structures (enregistrement)
Une structure est un type de donnée permettant de regrouper plusieurs variables qui
peuvent être de types différents.
struct Client
{
char Nom[20+1];
char Prenom[20+1];
int Matricule;
float Remuneration_totale;
};
……..
Client X; Client * pX;
……..
X.Matricule = 7834; // Accès au champ Matricule via l’opérateur point ( . )
pX = &X;
cout << pX -> Matricule; // Accès au champ Matricule via un pointeur vers l’objet
// grâce à l’opérateur flèche ( -> ).
// L’expression pX -> Matricule équivaut à (*pX).Matricule.
Toutefois, une structure ne peut contenir aucune instance d’elle-même. Par exemple, un
membre de type Client ne peut jamais être déclaré au sein de la définition de la structure
Client. Par contre, un pointeur vers une autre structure Client peut y être inclus.
Cet exemple permet le passage par référence des structures Client vers la fonction
d’affichage éliminant la surcharge associée au passage par valeurs qui aurait nécessité des
copies des structures pour les passer à la fonction d’affichage. De plus, l’utilisation de
const empêche la modification de la structure Client par la fonction d’affichage.
En C, les structures ne peuvent être affichées de façon globale; on doit plutôt mettre en
forme et afficher leurs membres l’un après l’autre. On peut écrire une fonction affichant
tous les membres d’une structure selon un format approprié quelconque. La surcharge de
l’opérateur << permet un affichage facile de variables d’un type structure.
- 21 -
Pointeurs
Ex. : char * p;
Client * Q;
char c;
……
p = &c;
…….
*p = "a"; // L’emploi de l’opérateur * de cette façon est ce
// qu’on appelle la déréférenciation d’un pointeur.
- 22 -
Une fonction peut aussi renvoyer l’adresse d’une variable.
(iii) utiliser l’arithmétique des pointeurs pour accéder aux éléments du tableau.
int Mois[12];
int * pEntier;
…
….
La notation pointeur peut être utilisée pour désigner les éléments du tableau ou
utiliser la notation tableau avec un pointeur.
- 23 -
int Mois[12];
int * pEntier;
pEntier = Mois;
….
}
….
Afficher("POO");
….
Afficher(Titre);
...
- 24 -
Quatre méthodes permettent de passer un pointeur à une fonction :
void Conversion(char * c)
{
// On peut modifier c et la chaîne pointée par c.
}
int main()
{
char chaine[] = "affichage des caracteres";
...
Affichage(chaine);
...
}
Cela pointe toujours vers le même emplacement mémoire et peut modifier les données
contenues à cet emplacement. Ceci est le cas par défaut pour un nom de tableau qui est en
fait un pointeur constant au début du tableau. On peut accéder à toutes les données du
tableau et les modifier en utilisant le nom et les indices du tableau.
- 25 -
Ex. : int x, y;
int * const ptr = &x;
*ptr = 7;
ptr = &y; // erreur
int main()
{
int a[] = {10, 20, 30};
essai(a) ;
...
}
void essai(const int b[])
{
...
}
Pointeurs et structures
#include <iostream.h>
#include <string.h>
struct Client
{
char Nom[20+1];
char Prenom[20+1];
int code;
};
void Afficher(Client * pC)
{
cout << pC -> Nom;
cout << pC -> Prenom;
cout << (*pC).code;
}
int main()
{
Client C;
strcpy(C.Nom, "BEAUDOIN");
strcpy(C.Prenom, "LUC");
C.code = 1234;
Afficher(&C);
Return 0;
}
- 26 -
Manipulation de pointeurs de fonctions
- Un pointeur peut être déclaré dans le but de contenir l’adresse d’une fonction.
- Cela permet d’appeler la fonction exactement de la même manière qu’avec son nom.
Ex. : int (*p) (int * pEntier, int N); // Déclaration du pointeur p de fonction.
Note :
(ii) Les pointeurs de fonction peuvent être utilisés par exemple dans le cas d’un outil
de gestion de menus.
Les opérateurs new et delete fournissent un moyen plus commode d’effectuer les tâches
d’allocation dynamique de la mémoire que les appels de fonctions malloc et free du
langage C.
Soit
Personne * ptrPersonne;
- 27 -
En C++, on a :
une variable de taille appropriée est automatiquement créée et l’opérateur new retourne
un pointeur de type correspondant.
delete ptrPersonne;
Le C++ permet de fournir un initialisateur pour une variable nouvellement créée comme,
par exemple,
float * ptrValeur = new float(3.14159);
et pour le détruire, on a :
delete [] ptrTableau;
Note :
- 28 -