La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Procédures et fonctions La modularité et ses avantages. Exemples en C. Notion de blocs et portée des identificateurs. Variables globales et variables locales.

Présentations similaires


Présentation au sujet: "Procédures et fonctions La modularité et ses avantages. Exemples en C. Notion de blocs et portée des identificateurs. Variables globales et variables locales."— Transcription de la présentation:

1 Procédures et fonctions La modularité et ses avantages. Exemples en C. Notion de blocs et portée des identificateurs. Variables globales et variables locales. Déclaration et définition de fonctions. Communication entre fonctions. Renvoi dun résultat. Paramètres formels et effectifs dune fonction. Mode de transmission des données par valeur ou par adresse. Tableau à une ou deux dimensions comme paramètre dentrée ou de sortie dune fonction. Les enregistrements comme paramètres de fonctions. Pile dexécution. Portée des variables. Le type « void ». Appels de fonctions. Fonction « main ». Fonctions arithmétiques standard. Décomposition dun programme en fonctions.

2 2 Les modules Jusquici, nous avons résolu nos problèmes à laide de fonctions prédéfinies (printf de stdio, strlen de string, …) et dune seule fonction nouvelle : la fonction principale main(). Pour résoudre des problèmes plus complexes, nous avons alors besoin de programmes longs, peu structurés et souvent peu compréhensibles. En plus, dans un même programme, on doit répéter plusieurs fois plusieurs suites dinstructions ce qui entraîne un gaspillage en espace mémoire. Objectif de ce chapitre : Définir et utiliser nos propres fonctions afin de rendre nos programmes modulaires. Définition dun module (une fonction en C) : Désigne une entité constituée de données et dinstructions agissant sur ces données qui fournissent une solution à une partie bien définie dun problème plus complexe. Un module peut faire appel à dautres modules, leur transmettre des données et en recevoir. Lusage de ces modules doit permettre de résoudre le problème original.

3 3 Avantages dun programme modulaire Meilleure lisibilité. Diminution du risque derreurs. Dissimulation des méthodes : Lors de lutilisation dun module, il faut seulement connaître son effet, sans devoir se préoccuper des détails de son implantation. Réutilisation de modules déjà existants : Cela permet dutiliser maintes fois une portion de code déjà écrite. Simplicité de lentretien : Des modifications peuvent être apportées à un module sans devoir toucher aux autres modules du programme. Favoriser le travail en équipe : Un programme peut être développé en équipe par délégation de la programmation des modules à différentes personnes ou groupes. Hiérarchisation des modules : Donne lieu à une méthodologie de program- mation (méthode de raffinement successif).

4 4 Modules fonctions en C Dans lenvironnement de programmation C ou C++, il existe plusieurs librairies de fonctions disponibles. Exemple :

5 5 Fonctions en tant que boîte noire Par exemple, sqrt retourne la racine carrée dun nombre x à virgule flottante passé en paramètre. On peut se servir de cette fonction sans connaître les détails de son implantation. Lors dun appel à cette fonction, la valeur du paramètre x est transmise à la fonction sqrt. 1. Lexécution de la fonction main est temporairement suspendue. 2. La fonction sqrt devient active et calcule la valeur de renvoi x. 3. Cette valeur de renvoi x est transmise en retour à la fonction main(). 4. La fonction main() termine le calcul en employant cette valeur. 5.

6 6 Fonctions en tant que boîte noire La valeur dentrée dune fonction nest pas obligatoirement une variable unique, mais peut être une expression quelconque dont le type correspond au type du paramètre. Exemple : b * b – 4 * a *c.

7 7 Usage de la fonction sqrt #include void main() { float a, b, c, discriminant; printf("Entrez les coefficients a, b, c : "); scanf("%f%f%f", &a, &b, &c); discriminant = (float) sqrt(b * b - 4 * a * c); printf("L'equation du second degre %f x * x + " "%f x + %f = 0 possede les racines suivantes :" " %f et %f.\n", a, b, c,(discriminant - b) / (2 * a), (discriminant + b) / (-2 * a)); }

8 8 Généralités sur les fonctions Certaines fonctions possèdent plusieurs entrées comme, par exemple, la fonction pow(x, y) possède 2 paramètres x et y en entrée et calcule x y. Toute fonction accepte des entrées et une valeur de renvoi dun type particulier. Ex. : sqrt accepte en entrée et comme valeur de renvoi un nombre. Pour définir notre propre fonction, nous avons la syntaxe suivante : type de la valeur de renvoi nom de la fonction (paramètre 1, paramètre 2, …, paramètre n ) { déclarations locales suite dinstructions } Ex. : double absolu(double x) { if (x >= 0) return x;else return –x; }

9 9 Modules fonctions en C Exemple I : Afficher à lécran un rectangle de longueur L et de hauteur H, formé dastérisques. ********************** H L #include // Affiche un rectangle formé d'astérisques. // Paramètres dentrée : // Longueur : longueur du rectangle, //Hauteur : hauteur du rectangle. // Valeur de renvoi : //Nil. void Rectangle(int Longueur, int Hauteur) { int i, j; for (i = 1; i <= Hauteur; i++) { for (j=1; j<=Longueur; j++) printf("*"); printf("\n"); } Cette fonction ne possède pas de valeur de renvoi.

10 10 Modules fonctions en C void main() { // Déclaration des variables de la fonction principale. int L,// Longueur du rectangle. H;// Hauteur du rectangle. // Saisie de la dimension du rectangle. printf("Entrez la longueur(L) et la hauteur(H) du rectangle : "); scanf("%d%d", &L,&H); // Affichage d'un rectangle L x H formé d'astérisques. Rectangle(L, H); } void main() Variables locales: L, H Fonction : Rectangle(L, H) void Rectangle(int Longueur, int Hauteur) Variables locales: Longueur, Hauteur, i, j

11 11 Modules fonctions en C main L H Rectangle Longueur Hauteur Les paramètres sont initialisés lors de lappel de la fonction. Note : Lordre dans lequel les fonctions sont définies est importante. Une fonction doit être définie avant son utilisation.

12 12 Calcul de la valeur dun compte dépargne Exemple II : Calculer la valeur dun compte dépargne possédant un solde initial s au bout de n années. Si le taux dintérêt est de p%, le solde au bout de n années est : s (1 + p / 100) n. #include // Calcule la valeur d'un compte d'épargne. // Paramètres dentrée : //s : valeur initiale de linvestissement, //n : le nombre dannées de conservation de linvestissement, //p : taux d'intérêt par année, en pourcentage, // Valeur de renvoi : //le solde après n années. double Valeur_Compte(double s, int n, double p) { double b = s * pow(1.0 + p / 100.0, (double) n); return b; } Linstruction return permet de retourner la valeur de renvoi. On aurait pu écrire : return s * pow(1.0 + p / 100.0, (double) n);

13 13 Calcul de la valeur dun compte dépargne void main() { // Déclaration des variables de la fonction principale. float solde_initial; int periode; float taux_d_interet; // Entrée des trois paramètres de la fonction. printf("Entrez le solde initial, la periode et le taux d'interet : "); scanf("%f%i%f", &solde_initial, &periode, &taux_d_interet); // Affichage de la valeur du compte d'épargne. printf("\nValeur du compte d'epargne : %f\n", Valeur_Compte(solde_initial, periode, taux_d_interet)); } Note : On a pensé à la réutilisation lors de la définition de la fonction Valeur_Compte en optant pour 3 paramètres clés.

14 14 Présence de commentaires Les commentaires sont là pour le bénéfice des humains et non pour les compilateurs. Parmi les humains visés, la priorité doit être donnée à lutilisateur de la fonction plutôt quau programmeur. Les commentaires présents doivent décrire précisément le rôle joué par cette fonction et non des détails dimplantation. Écrire dabord les commentaires propres à une fonction avant son code. Cela permet de vérifier votre compréhension du rôle joué par cette fonction. Ajouter, le cas échéant, les conditions qui sappliquent aux paramètres dentrée. Ces conditions seront prises en compte plus tard. Ex. : // Calcule la sommation suivante : n. // Paramètre dentrée : //n :le nombre de termes dans la sommation. //n 1. // Valeur de renvoi : //la valeur de lexpression : n (n + 1) / 2.

15 15 Renvoi du résultat Lorsque linstruction return est exécutée, la fonction prend fin immédiatement avec la transmission de la valeur de retour. double Valeur_Compte(double s, int n, double p) { if(n == 0 || p == 0) return s; double b = s * pow(1.0 + p / 100.0, (double) n); return b; } Il est important que chaque alternative à lintérieur de la fonction nous mène à une instruction return. double Valeur_Compte(double s, int n, double p) { if(n >= 0 && p >= 0) return s * pow(1.0 + p / 100.0, (double) n); } Le type du résultat peut être un type simple, un type pointeur, un type struct, un type union ou void. Une fonction ne peut pas fournir comme résultat un tableau, une chaîne de caractères ou une fonction mais un pointeur sur le 1 e élément dun tableau ou dune chaîne de caractères.

16 16 Fonction prédicat Une fonction prédicat est une fonction qui retourne une valeur TRUE ou FALSE. #include // Détermine si un nombre entier positif est premier ou non. // Paramètre d'entrée : //n :un nombre entier positif. // Valeur de renvoi : //TRUEsi n est un nombre premier, //FALSEautrement. bool Premier(int n) { for (int i = 2; i <= (int) sqrt(n); i++) if ((n%i) == 0) return false; return true; }

17 17 Fonction prédicat void main() { int entier; cout << "Entrez un nombre entier : "; cin >> entier; if (Premier(entier)) cout << entier << " est un nombre premier.\n"; else cout << entier << " n'est pas un nombre premier.\n"; }

18 18 Paramètres Lors de lexécution dune fonction, les paramètres de la fonction sont dabord initialisés à partir des expressions fournies lors de lappel. Il sagit simplement dune copie où la vérification de types est effectuée. #include int min(int u, int v, int w) { if (u < v) v = u; if (v < w) w = v; return w; } void main() { int A = 3, B = 2; cout << min(A, 2, A + B); } Les paramètres u, v, w de la fonction peuvent être modifiés par la suite; cela na pas dimpact sur la fonction appelante. Expressions permettant dinitialiser les paramètres de la fonction lors de lappel. Mauvaise habitude : cela porte à confusion (voir plus loin).

19 19 Noms significatifs pour les paramètres Choisir des noms explicites pour des paramètres possédant un rôle spécifique et des noms simples pour ceux restant génériques. Objectif : Le lecteur doit comprendre le but du paramètre sans avoir à lire sa description. Exemples : double sin(double radian)est préférable à double sin(double x). Cela précise que langle ne peut être fourni en degrés. En C++, double atan2(double y, double x) porte à confusion. Est-ce tan -1 (x / y) ou tan -1 (y / x) ? Écrivons plutôt : double atan2(double numerator, double denominator) bool approx_egal(double x, double y) //Des noms simples sont appropriés.

20 20 Valeurs par défaut pour les paramètres Évalue un polynôme de degré 3 de la forme : a 0 + a 1 x + a 2 x 2 + a 3 x 3. Paramètres d'entrée : a 0, a 1, a 2, a 3 :les coefficients du polynôme, x :la valeur de la variable indépendante. Valeur de renvoi : la valeur du polynôme de degré 3. #include float Polynome_de_degre_3 (float x, float a0, float a1 = 0, float a2 = 0, float a3 = 0) { return a0 + (a1 + (a2 + a3 * x) * x) * x; } Exemple : valeurs par défaut

21 21 Valeurs par défaut pour les paramètres void main() { float x = 2.3f; cout << "La valeur du polynome pour x = " << x << " est : " << Polynome_de_degre_3(x, 7) << endl; cout << "La valeur du polynome pour x = " << x << " est : " << Polynome_de_degre_3(x, 7, 6) << endl; cout << "La valeur du polynome pour x = " << x << " est : " << Polynome_de_degre_3(x, 7, 6, 5) << endl; cout << "La valeur du polynome pour x = " << x << " est : " << Polynome_de_degre_3(x, 7, 6, 5, 4) << endl; cout << endl << endl; }

22 22 Déclaration de prototypes de fonctions Une fonction doit être connue avant dêtre employée. Nous avons résolu le problème jusquà maintenant en définissant dabord les fonctions élémentaires puis, les fonctions de plus haut niveau et, finalement, la fonction main. Il se peut quune fonction f appelle une fonction g et g fasse de même avec f. On doit alors déclarer au début le prototype dune fonction pour pouvoir lappeler avant quelle ne soit définie. type de la valeur de renvoi nom de la fonction (paramètre 1, paramètre 2, …, paramètre n ); Idem à la définition dune fonction mais sans le corps de la fonction et avec le point-virgule. Exemple :int max(int u, int v); Cela indique que la fonction est définie ailleurs, soit plus loin dans le fichier actuel soit dans un autre fichier. Les déclarations de fonctions classiques comme sqrt sont contenues dans les fichiers den-tête comme cmath.

23 23 Déclaration de prototypes de fonctions Certains programmeurs préfèrent énumérer tous les prototypes de fonction en haut du fichier, puis écrire main et ajouter la définition des fonctions. Exemple I : #include // Affiche un rectangle formé d'astérisques. // // Paramètres dentrée : // Longueur :longueur du rectangle, //Hauteur :hauteur du rectangle. // // Valeur de renvoi : //Nil. void Rectangle(int Longueur, int Hauteur); Lors de la déclaration, le nombre et le type des paramètres doivent nécessairement correspondre à ceux de la définition de la fonction.

24 24 Déclaration de prototypes de fonctions void main() { // Déclaration des variables de la fonction principale. int L,// Longueur du rectangle. H;// Hauteur du rectangle. // Saisie de la dimension du rectangle. printf("Entrez la longueur(L) et la hauteur(H) du rectangle : "); scanf("%d%d", &L,&H); // Affichage d'un rectangle L x H formé d'astérisques. Rectangle(L, H); } void Rectangle(int Longueur, int Hauteur) { int i, j; for (i = 1; i <= Hauteur; i++) { for (j=1; j<=Longueur; j++) printf("*"); printf("\n"); }

25 25 Déclaration de prototypes de fonctions Exemple II :

26 26 Effets secondaires à éviter Examinons la fonction suivante : double Valeur_Compte(double s, int n, double p) { if(n == 0 || p == 0) return s; double b = s * pow(1.0 + p / 100.0, (double) n); return b; } Pourquoi la fonction nimprimerait-elle pas la valeur en même temps ? double Valeur_Compte(double s, int n, double p) { if(n == 0 || p == 0) return s; double b = s * pow(1.0 + p / 100.0, (double) n); cout << "Le solde est maintenant " << b << endl; return b; } Un principe à respecter :une fonction ne doit laisser aucune trace à part renvoyer une valeur.

27 27 Effets secondaires à éviter Une autre mauvaise pratique est dimprimer des messages derreur à lintérieur dune fonction. double Valeur_Compte(double s, int n, double p) { if(n < 0 || p < 0) { cout << "n ou p sont invalides."; return 0; } double b = s * pow(1.0 + p / 100.0, (double) n); return b; }

28 28 Modes de transmission des paramètres Jusquà maintenant, nous avons opté pour un mode de transmission des paramètres par valeur qui consiste à copier la valeur des expressions lors de lappel de la fonction dans chaque paramètre de la fonction. Avantage :La fonction appelée ne peut pas altérer le contenu des variables de la fonction appelante. Supposons maintenant que nous voulons écrire une fonction Lecture spécifiée comme suit : #include // Lire un nombre entier positif et ranger cette valeur dans la variable // de la fonction appelante. // // Paramètre de sortie //*n :conservera la valeur entière positive lue. Pour y arriver, on doit transmettre dans la fonction appelante ladresse de la variable entière qui conservera la valeur lue et la fonction appelée doit déclarer le paramètre comme pointeur.

29 29 Mode de transmission par adresse void Lecture(int * n) { int i = -1; while (i < 0) scanf("%i", &i); *n = i;// Range la valeur de i dans la variable pointée par n. } void main() { int j = 1; Lecture(&j);// Ladresse de la variable j est transmise. printf("%i", j);// Le contenu de j est modifié à partir de la valeur lue. } main Lecture j 1 n à lappel après la lecture j 24 n au retour de la fonction j 24 *n = -1; while (*n < 0) scanf("%i", n); ou encore

30 30 Mode de transmission par adresse Exemple III : Écrire une fonction PERMUTER qui échange le contenu de 2 variables de type int. Pour modifier le contenu de X et Y, PERMUTER a besoin des adresses de X et Y.

31 31 Mode de transmission par adresse

32 32 Exemple de fonctions en C Exemple IV : Tableau de valeurs dune fonction. Soit F(x) = x 3 – 2 x + 1, on désire construire un tableau de valeurs de cette fonction où N (le nombre de valeurs) ainsi que les valeurs de x sont entrés au clavier. #include void Lire_Nombre_d_evaluations(int * n); // Lecture du nombre d'évaluations à effectuer. // // Paramètre de sortie : // //*n :contiendra le nombre d'évaluations à réaliser.

33 33 Exemple de fonctions en C void Lire_Vecteur_reel(int n, float x[]); // Lecture des n composantes réelles d'un vecteur x. // // Paramètre d'entrée : // //n :le nombre de composantes du vecteur x, // // Paramètre de sortie : // //x[] :contiendra les n composantes à évaluer. x désigne ladresse de la 1 ière composante du vecteur.

34 34 Exemple de fonctions en C void Calculer_Valeurs(int n, float x[], float F[]); // Calcul de la valeur de la fonction pour chaque composante // dans x. // // Paramètres d'entrée : // //n :le nombre de composantes à évaluer, //x[] :les n composantes du vecteur à évaluer. // // Paramètre de sortie : // //F[] :contiendra la valeur de la fonction //pour chaque composante du vecteur à évaluer.

35 35 Exemple de fonctions en C void Afficher_Resultats(int n, float x[], float F[]); // Affichage de n valeurs réelles et de la valeur de la fonction pour chaque // valeur réelle. // // Paramètres d'entrée : // //n :le nombre de composantes évaluées, //x[] :les n composantes évaluées, //F[] :contient la valeur de la fonction pour chaque //composante.

36 36 Exemple de fonctions en C void main() { float Valeurs_de_x[100];// Valeurs de x. float Valeurs_de_F[100];// Valeurs de F(x). int Nombre_d_evaluations; Lire_Nombre_d_evaluations(&Nombre_d_evaluations); Lire_Vecteur_reel(Nombre_d_evaluations, Valeurs_de_x); Calculer_Valeurs(Nombre_d_evaluations,Valeurs_de_x,Valeurs_de_F); Afficher_Resultats(Nombre_d_evaluations,Valeurs_de_x,Valeurs_de_F); }

37 37 Exemple de fonctions en C void Lire_Nombre_d_evaluations(int * n) { do { cout << "Entrez un entier entre 1 et 100 : "; cin >> *n; } while (*n 100); } void Lire_Vecteur_reel(int n, float x[]) { cout << "Entrez " << n << " nombres reels :\n"; for (int i = 0; i > x[i]; }

38 38 Exemple de fonctions en C void Calculer_Valeurs(int n, float x[], float F[]) { float Fonction(float x); // Retourne la valeur de la fonction évaluée à x. // // Paramètre d'entrée : // //x :valeur réelle. // // Valeur de renvoi : // //Valeur de la fonction évaluée à x. for (int i = 0; i < n; i++) F[i] = Fonction(x[i]); } Note : Il est interdit de définir des fonctions à lintérieur dune autre fonction.

39 39 Exemple de fonctions en C float Fonction(float x) { return x * x * x - 2 * x + 1; } void Afficher_Resultats(int n, float x[], float F[]) { cout << "\n X : "; for (int i = 0; i < n; i++) cout << setw(10) << x[i]; cout << "\n F(X) : "; for (i = 0; i < n; i++) cout << setw(10) << F[i]; cout << endl; }

40 40 Modes de transmission par valeur ou par adresse Pour des raisons de sécurité, on ne choisit pas un mode de transmission par adresse si notre objectif consiste uniquement à transmettre la valeur dune expression à une fonction. En optant pour un mode de transmission par adresse, lexpression lors de lappel dune fonction doit être obligatoirement ladresse dune variable. Ex. : Lecture(5); Lecture(u + v);

41 41 Passage de ladresse dun tableau à une dimension Comme il est impossible de passer le contenu de tout un tableau à une fonction, on fournit ladresse dun élément du tableau. En général, on fournit ladresse du premier élément du tableau, qui est donnée par le nom du tableau. Déclaration : Dans la liste des paramètres dune fonction, on peut déclarer un tableau par le nom suivi de crochets : type des composantes nom du tableau [] ou simplement par un pointeur sur le type des éléments du tableau : type des composantes * nom du tableau

42 42 Passage de ladresse dun tableau à une dimension Exemple :

43 43 Passage de ladresse dun tableau à une dimension Appel : Ladresse dun tableau peut être donnée par le nom du tableau, par un pointeur ou par ladresse dun élément quelconque du tableau. Exemple :

44 44 Particularités avec un tableau qui nest pas du type char Il faut fournir la dimension du tableau ou le nombre déléments à traiter comme paramètre, sinon la fonction risque de sortir du domaine du tableau. Exemple : Lecture de N données dans un tableau.

45 45 Passage de ladresse dun tableau à 2 dimensions Problème : Écrire une fonction qui calcule la somme de tous les éléments dune matrice de réels dont nous fournissons les 2 dimensions N et M comme paramètres. Comment passer ladresse de la matrice à la fonction ? 1 e option :Déclarer le tableau dans len-tête de la fonction sous la forme A[][]. Le compilateur a besoin de la 2 ième dimension de A pour déterminer ladresse de A[i][j]. 2 e option : La fonction recevra un pointeur de type float * au début de la matrice. Il sagit de parcourir tous les éléments comme sil sagissait dun tableau à une dimension N*M.

46 46 Passage de ladresse dun tableau à 2 dimensions Appel de la fonction : Il faut transmettre ladresse du début du tableau. Prenons par exemple un tableau déclaré par :float A[3][4]; Le nom A correspond à la bonne adresse, mais cette adresse est du type pointeur sur un tableau de 4 éléments de type float. La conversion aura lieu automatiquement mais vous recevrez un message davertissement. On peut éviter ceci à laide dune conversion explicite.

47 47 Passage de ladresse dun tableau à 2 dimensions Lidéal est de renvoyer explicitement ladresse du 1 e élément du tableau : SOMME(&T[0][0], 3, 4).

48 48 Notion de bloc et portée des identificateurs #include void main() { int i = 5; if (i == 5) { int j; for (j = 1; j <= i; j++)printf("%i", j); } Les fonctions en C sont définies à laide de blocs dinstructions. Un bloc dinstructions est encadré daccolades et composé de 2 parties : { déclarations locales instructions } Exemple : Cela est vrai aussi pour les commandes if, while ou for.

49 49 Variables locales Les variables déclarées dans un bloc dinstructions sont uniquement visibles à lintérieur de ce bloc. Ce sont des variables locales à ce bloc. Ex. : Aucune autre fonction na accès à la variable NOM : Ex. : La déclaration de la variable I nest pas visible à lextérieur du bloc dinstructions conditionnel, ni dans la fonction qui lentoure.

50 50 Variables locales Une variable déclarée à lintérieur dun bloc cache toutes les variables de même nom des blocs qui lentourent. Réfère à la variable de type int. Réfère à la variable de type double. La variable X de type int nest pas accessible. Note :Éviter de cacher des variables; cela peut mener à des malentendus. Effectuer toutes nos déclarations locales au début des fonctions. Les paramètres dune fonction sont des variables locales initialisées par les valeurs obtenues lors de lappel.

51 51 Passage des paramètres par valeur : exemple La fonction ETOILES dessine une ligne de N étoiles. Le paramètre N est modifié à lintérieur de la fonction. La fonction TRIANGLE, appelle la fonction ETOILES en utilisant la variable L comme paramètre : Au moment de lappel, la valeur de L est copiée dans N. N peut donc être décrémentée à lintérieur de ETOILES sans influencer la valeur originale de L.

52 52 Passage des paramètres par valeur : exemple

53 53 Variables globales Les variables déclarées au début du fichier, à lextérieur de toutes les fonctions sont disponibles partout. Ce sont des variables globales. Exemple : La variable STATUS est déclarée globalement pour pouvoir être utilisée dans les procédures A et B.

54 54 Usage des variables globales Écrire nos programmes aussi localement que possible. Les fonctions ont accès à des données qui ne leur appartiennent pas. Les données ne sont pas protégées. Un programme nest plus constitué de composantes indépendantes; Ces variables globales créent des liens entre les fonctions. Lors de la définition dune fonction, il est nécessaire de connaître le traitement accordé aux variables globales dans les autres fonctions. Solution :Usage de classes.

55 55 Règles pour la déclaration de fonctions (prototype) De façon analogue aux déclarations de variables, nous pouvons déclarer une fonction localement ou globalement. Déclaration locale La fonction est déclarée localement dans la fonction qui lappelle avant la déclaration des variables. Elle est alors disponible à cette fonction. Déclaration globale La fonction est déclarée globalement au début du programme après les instructions #include. Elle est alors disponible à toutes les fonctions du programme. Déclaration implicite par la définition La fonction est disponible à toutes les fonctions qui suivent sa définition. main La fonction principale main na pas besoin dêtre déclarée.

56 56 Règles pour la déclaration de fonctions : exemple Considérons la hiérarchie suivante :mainFAFB Il y a plusieurs possibilités pour déclarer et définir ces 3 fonctions. 1 e cas : Déclarations locales des fonctions et définition top-down. Avantage : Reflète la hiérarchie des fonctions. Facile pour un usager qui ne sintéresse quà la solution globale du problème.

57 57 Règles pour la déclaration de fonctions : exemple 2 ième cas : Définition bottom-up sans déclarations. Elle débute en bas de la hiérarchie et termine avec la fonction main. Les fonctions qui traitent des détails sont définies en premier lieu. Inconvénient : Il est plus difficile de retrouver les dépendances entre les fonctions.

58 58 Règles pour la déclaration de fonctions : exemple 3 ième cas : Déclaration globale des fonctions et définition top-down. Approche la plus simple car nous ne sommes pas forcés de nous occuper de la dépendance entre les fonctions.

59 59 Pointeurs de fonctions Un pointeur vers une fonction contient ladresse de la fonction en mémoire i.e. ladresse mémoire du début du code de la fonction. Les pointeurs vers des fonctions peuvent être passés aux fonctions ou renvoyés, être stockés dans des tableaux et être affectés à dautres pointeurs de fonction. Exemple :Tri dun tableau dentiers en ordre croissant ou décroissant. Tiré de Deitel & Deitel, Comment Programmer en C++. Prentice-Hall, #include // Vérifie si le 1e paramètre est plus grand que le 2e. // // Paramètres d'entrée : //a, b :2 valeurs entières, // Valeur de renvoi : //TRUE :si a > b,FALSE :si a <= b. bool ascendant(int a, int b) {return a > b;}

60 60 Pointeurs de fonctions // Vérifie si le 1e paramètre est plus petit que le 2e. // // Paramètres d'entrée : //a, b :2 valeurs entières, // // Valeur de renvoi : //TRUE :si a < b, //FALSE :si a >= b. bool descendant(int a, int b) { return a < b; }

61 61 Pointeurs de fonctions // Permutation du contenu de 2 variables entières. // // Paramètres d'entrée : //int * pA, int * pB :contient l'adresse des 2 variables entières //à permuter. // // Paramètres de sortie : //int * pA, int * pB :contient l'adresse des 2 variables entières //dont les valeurs ont été permutées. void permutation(int * pA, int * pB) { int temporaire = * pA; * pA = * pB; * pB = temporaire; }

62 62 Pointeurs de fonctions // Tri des composantes d'un tableau d'entiers dans un ordre particulier. // // Paramètres d'entrée : //int tableau[] :renferme un tableau d'entiers à ordonner, //int dimension :renferme le nombre de composantes du tableau, //bool (*comparer)(int a, int b) : //pointeur vers une fonction booléenne qui retourne //TRUE si les paramètres a et b doivent être permutés. // // Paramètres de sortie : //int tableau[] :renferme le tableau d'entiers après ordonnancement. void bulle(int tableau[], int dimension, bool (*comparer)(int a, int b)) { void permutation(int * pA, int * pB); for (int i = 1; i < dimension; i++) for (int j = 0; j < dimension - 1; j++) if ((*comparer)(tableau[j], tableau[j+1])) permutation(&tableau[j], &tableau[j+1]); }

63 63 Pointeurs de fonctions void main() { const int dimensionTableau = 10; int Tableau_a_trier[dimensionTableau] = {2, 6, 4, 8, 10, 12, 89, 68, 45, 37}; int choix; cout << "Entrez 1 pour un tri en ordre croissant,\n" << "entrez 2 pour un tri en ordre decroissant : "; cin >> choix; // Affichage des données dans lordre initial. cout << "\n\nAffichage des donnees dans l'ordre initial : \n"; for (int i = 0; i < dimensionTableau; i++) cout << setw(4) << Tableau_a_trier[i]; cout << endl << endl;

64 64 Pointeurs de fonctions // Tri des éléments du tableau en ordre croissant ou décroissant. if (choix == 1) { bulle(Tableau_a_trier, dimensionTableau, ascendant); cout << "Affichage des donnees en ordre croissant : \n"; } else { bulle(Tableau_a_trier, dimensionTableau, descendant); cout << "Affichage des donnees en ordre decroissant : \n"; } // Affichage des données une fois triée. for (i = 0; i < dimensionTableau; i++) cout << setw(4) << Tableau_a_trier[i]; cout << endl << endl; }

65 65 Pointeurs de fonctions Un pointeur vers une fonction est aussi utilisé dans les systèmes pilotés par menus où lutilisateur doit sélectionner une option parmi les choix proposés qui correspondent chacun à une fonction différente. Les pointeurs vers chaque fonction sont stockés dans un tableau de pointeurs vers des fonctions. Le choix de lutilisateur sert dindice au tableau, tandis que le pointeur appelle la fonction. Exemple : #include // Calcule la somme de 2 entiers. // // Paramètres d'entrée : //a, b :2 valeurs entières, // // Valeur de renvoi : a + b //la somme de a et de b. int somme(int a, int b) { return a + b; }

66 66 Pointeurs de fonctions // Calcule la différence de 2 entiers. // // Paramètres d'entrée : //a, b :2 valeurs entières, // // Valeur de renvoi : a - b //la différence de a et de b. int difference(int a, int b) {return a - b;} // Calcule le produit de 2 entiers. // // Paramètres d'entrée : //a, b :2 valeurs entières, // // Valeur de renvoi : a * b //le produit de a et de b. int produit(int a, int b) {return a * b;}

67 67 Pointeurs de fonctions // Calcule le quotient de 2 entiers. // // Paramètres d'entrée : //a, b :2 valeurs entières, // // Valeur de renvoi : a / b //le quotient de a avec b. int quotient(int a, int b) { return a / b; }

68 68 Pointeurs de fonctions void main() { int (*f[4])(int a, int b) = { somme, difference, produit, quotient}; int u = 5,v = 2; int choix; cout << "\nEntrez un nombre entre 0 et 3, ou 4 pour terminer: "; cin >> choix; while (choix >= 0 && choix <= 3) { cout << (*f[choix])(u, v); cout << "\nEntrez un nombre entre 0 et 3, ou 4 pour terminer: "; cin >> choix; }

69 69 Structures et fonctions une structure comme argument dune fonction: #include struct etudiant { int matricule;int age; char nom[20];char prenom[20]; }; void main() { bool meme_age(struct etudiant E1, struct etudiant E2); struct etudiant P = { , 23, "Dugre", "Luc"}; struct etudiant Q = { , 20, "Dupre", "Leon"}; if (meme_age(P, Q)) cout << "Ils sont de meme age.\n"; else cout << "Ils sont d'ages differents.\n"; } bool meme_age(struct etudiant E1, struct etudiant E2) { return E1.age == E2.age; } Rien dinhabituel.

70 70 Structures et fonctions un pointeur à une structure comme argument dune fonction : Si la structure possède un grand nombre de champs, il est préférable dopter pour un pointeur vers la structure plutôt que la structure elle-même. Motifs : Économie mémoire et réduction du temps dexécution. #include struct etudiant { int matricule;int age; char nom[20]; char prenom[20]; }; void main() { bool meme_age(struct etudiant const * pE1, struct etudiant const * pE2); struct etudiant P = { , 23, "Dugre", "Luc"}; struct etudiant Q = { , 20, "Dupre", "Leon"}; if (meme_age(&P, &Q)) cout << "Ils sont de meme age.\n"; else cout << "Ils sont d'ages differents.\n"; } bool meme_age(struct etudiant const * pE1, struct etudiant const * pE2) {return (* pE1).age == (* pE2).age;} Des pointeurs à des structures constantes nous empêchant de modifier le contenu des structures.

71 71 Structures et fonctions un pointeur à une structure comme argument dune fonction (suite) : On ajoute const pour empêcher que lon modifie les données dans la fonction. La fonction meme_age nécessite un accès en lecture seulement des paramètres. Réécrivons la fonction précédente : bool meme_age(struct etudiant * const pE1, struct etudiant * const pE2) { return (* pE1).age == (* pE2).age; } Des pointeurs constants à des structures qui nous empêchent de modifier le contenu des pointeurs mais non celui des structures.

72 72 Structures et fonctions une structure comme valeur de renvoi dune fonction : #include struct etudiant { int matricule;int age; char nom[20];char prenom[20]; }; void main() { struct etudiant plus_jeune(struct etudiant E1, struct etudiant E2); struct etudiant P = { , 23, "Dugre", "Luc"}; struct etudiant Q = { , 20, "Dupre", "Leon"}; cout << "Le plus jeune a comme age " << plus_jeune(P, Q).age << " ans.\n"; } struct etudiant plus_jeune(struct etudiant E1, struct etudiant E2) { if (E1.age < E2.age) return E1;else return E2; } Note : La valeur de renvoi pourrait être un pointeur vers une structure.


Télécharger ppt "Procédures et fonctions La modularité et ses avantages. Exemples en C. Notion de blocs et portée des identificateurs. Variables globales et variables locales."

Présentations similaires


Annonces Google