Vous êtes sur la page 1sur 10

Element d'enseignement Atelier de Programmation 2

Niveau License Appliquée Classe: LAII-1A, 1B,1C,


enInformatiqueIndustrielle 1D

TP N°2 : Atelier de programmation 2


Objectifs Les Fonctions
Boite à outils logiciels CodeBlocks

Exercice1:

Dans cet exercice, on vous demande de faire un programme qui :


‐ Demande à l’utilisateur d’entrer au clavier deux nombres entiers.
‐ Stocke ces données dans des variables.
‐ Fait appel à une fonction Mini(…) qui retourne le plus petit des 2 nombres.
‐ Affiche le plus petit des 2 nombres dans le programme principal.

Exercice 2 :
Ecrire un programme se servant d'une fonction MOYENNE du type float pour afficher la moyenne arithmétique
de deux nombres réels entrés au clavier.

Exercice 3 :

Ecrire une fonction FACT du type double qui reçoit la valeur N (type int) comme paramètre et qui
fournit la factorielle de N comme résultat. Ecrire un petit programme qui teste la fonction FACT.
On définit la fonction factorielle de la manière suivante:
0! = 1
n! = n*(n-1)*(n-2)* ... * 1 (pour n>0)

Exercice 4:
Ecrire la fonction SOMME_TAB qui calcule la somme des N éléments d'un tableau TAB du type int. N et TAB
sont fournis comme paramètres; la somme est retournée comme résultat du type long.

Exercice 5 :

Écrire un programme qui lit un tableau A d'une dimension inférieure ou égale à 100 et affiche le
tableau et la somme des éléments du tableau.

Exercice 6 :
Ecrire la fonction SOMME_MATRICE du type long qui calcule la somme des éléments d'une matrice MAT du
type int. Choisir les paramètres nécessaires. Ecrire un petit programme qui teste la fonction
SOMME_MATRICE.

1
Elément d'enseignement Atelier de programmation
Niveau License Appliquéeen Informatique Classe: LAII-1A, 1B,1C, 1D
Industrielle
Tp N°2 : Atelier de programmation 2
Objectifs Les Fonctions
Boite à outils logiciels CodeBlocks

Introduction
La structuration de programmes en sous-programmes se fait en C à On peut se contenter de déclarer le prototype d’une fonction (sans le
l’aide de fonctions. L’utilisation de fonctions est déjà vue, par corps) :
exemple avec celles prédéfinies dans des bibliothèques standards
(comme printf de <stdio.h>, malloc de <stdlib.h> etc...) ou encore la type_résultat nom_fonction (type1 arg1, . . . ,type n arg n) ;
fonction d’entrée main.
Dans ce cas, la définition de la fonction (avec le corps des
I. Déclaration et définition d’une fonction instructions qui la compose) peut être déclarée ailleurs dans le
programme.
Le format général d’une définition de fonction est de la forme :
• Une fonction ne peut pas fournir comme résultat des tableaux, des
type_résultat nom_fonction (type1 arg1, . . . , type n arg n) chaînes de caractères ou des fonctions, mais il est cependant
{ possible qu’elle renvoi un pointeur sur le premier élément d’un
<d´éclarations de variables locales > tableau ou d’une chaîne decaractères.
<liste d’instructions>
} • Si une fonction ne fournit pas de résultat, il faut indiquer void
comme type de résultat.
Dans cette définition, on rappelle que :
– type_résultat correspond au type du résultat de la fonction. Exemple : void print_liste ( liste L ){...}
– nom_fonction est le nom qui identifie la fonction.
– type1 arg1 . . . type n arg n définit les types et les noms des • Si la fonction n’a pas de paramètres, on peut déclarer la liste des
paramètres de la fonction. Ces arguments sont appelés paramètres paramètres comme (void) ou simplement comme ().
formels, on trouve aussi les paramètres effectifs qui sont les
paramètres avec lesquels la fonction est effectivement appelée. Exemple : int main( ){...} // equivalent à 'int main(void){...}'

2
L’ordre et le type des paramètres effectifs de la fonction doivent
• L’ordre des définitions de fonctions dans le texte du programme ne concorder avec ceux donnés dans la définition de l’en-tête de la
joue pas de rôle, mais chaque fonction doit être déclarée ou définie fonction. Les parameters effectifs peuvent être des expressions.
avant d’être appelée.
• Dans le cas où type_resultat est différent du type void, le corps de la III. Durée de vie des identificateurs
fonction doit obligatoirement comporter une instruction return, dite
instruction de retour à la fonction appelante. Les variables manipulées dans un programme C ne sont pas toutes
Elle à comme syntaxe : return expression; traitées de la même manière. En particulier, elles n’ont pas toutes la
La valeur de l’expression correspond à la valeur que même durée de vie.
retourne la fonction et doit donc être de type On distingue deux catégories de variables.
type_resultat.
a) Les variables permanentes (ou statiques)
• Enfin, il faut noter que les variables éventuellement déclarées au sein Une variable permanente occupe un emplacement en mémoire qui
d’une fonction seront locales à celle-ci et n’auront plus de sens que reste le même durant toute l’exécution du programme. Cet
dans le corps de la fonction. De même, les identificateurs des emplacement est alloué lors de la compilation. La partie de la
arguments de la fonction (arg1,. . . ,argn) n’ont d’importance qu’à mémoire contenant les variables permanentes est appelée segment de
l’intérieur de celle-ci. données. Par défaut, les variables permanentes sont initialisées à
zéro par le compilateur.
II.Appel d’une fonction Elles sont caractérisées par le mot-clef static.

L’appel d’une fonction se fait par l’expression: nomfonction( b) Les variables temporaires
arg1, . . . ,argn). L’ emplacement en mémoire est alloué de façon dynamique lors de
l’exécution du programme. Elles ne sont pas initialisées par

3
défaut. Leur emplacement en mémoire est libéré par exemple à la Une variable globale est donc une variable déclarée en dehors de
fin de l’exécution d’une fonction secondaire. toutes fonctions, au début du fichier, à l’extérieur de toutes les
Par défaut, les variables temporaires sont situées dans la partie de la fonctions et sont disponibles à toutes les fonctions du programme.
mémoire appelée segment de pile. Dans ce cas, la variable est dite En général, les variables globales sont déclarées immédiatement
automatique. Le spécificateur de type correspondant, auto, est derrière les instructions #include au début du programme.
rarement utilisé puisqu’il ne s’applique qu’aux variables Elles sont systématiquement permanentes.
temporaires qui sont automatiques par défaut.
Remarque : Les variables déclarées au début de la fonction
a) Portée des variables principale main ne sont pas des variables globales, mais locales à
Selon l’endroit où on déclare une variable, celle-ci pourra être main !
accessible (visible) partout dans le code ou seulement dans une
partie de celui-ci (à l’intérieur d’une fonction typiquement), on parle Exemple :
de la portée (ou visibilité) de la variable. La variable STATUS est déclarée globalement pour pouvoir être
Lorsqu’une variable est déclarée dans le code même, c’est-`a-dire à utilisée dans les procédures A et B.
l’extérieur de toutes fonctions ou de blocs d’instructions, elle est #include<stdio.h>
accessible de partout dans le code (n’importe quelle fonction du int STATUS;
programme peut faire appel à cette variable). On parle alors de void A(...){
variable globale. ...
Lorsque l’on déclare une variable à l’intérieur d’un bloc if (STATUS>0)
d’instructions (entre des accolades), sa portée se limite à l’intérieur STATUS--;
du bloc dans lequel elle est déclarée. else
On parle de variable locale. ...

b) Variables globales

4
...
}
void B(...) {
... IV.Récursivité
STATUS+; Comme pour beaucoup de langages, la récursivité est possible en C.
... Qu’est ce qu’on entend par la récursivité? C’est la propriété qu’une
} fonction peut s’auto-appeler, c’est-à-dire de se rappeler elle-même
plusieurs fois. La notion de récurrence est largement présente dans le
c) Variables locales domaine mathématique, notamment dans la définition des suites.
Exemple :
Les variables déclarées dans un bloc d’instructions sont uniquement
visibles à l’intérieur de ce bloc. On dit que ce sont des variables
locales à ce bloc.

Exemple : la variable nom est définie localement dans le bloc


extérieur de la fonction hello. Ainsi, aucune autre fonction n’a accès
à la variable nom : Les premiers termes consécutifs de cette suite sont donc :

voidhello() {
char nom[20];
printf("Introduisez votre nom : ");
scanf("%s",&nom);
printf("Bonjour %s !\n", nom); Bien sûr, on pourrait calculer explicitement la valeur en fonction de
} n directement.

5
En ce qui concerne le passage de paramètres à une procédure, le
programmeur a deux besoins fondamentaux :
– Soit il désire passer une valeur qui sera exploitée par l’algorithme
de la fonction (c’est ce dont on a besoin quand on écrit par exemple
sin(x)). Une façon de passer un paramètre s’appelle passage par
valeur.
– Soit il désire passer une référence à une variable, de manière à
permettre à la fonction de modifier la valeur de cette variable. C’est
ce dont on a besoin quand on écrit une fonction réalisant le produit
de deux matrices prodmat (a,b,c) où l’on veut qu’en fin d’exécution,
la matrice c soit égale au produit matriciel des matrices a et b.
prodmat a besoin des valeurs des matrices a et b, et d’une référence
vers la matrice c. Une telle façon de passer un paramètre s’appelle
du passage par adresse.
...

a) Passage des paramètres par valeur

En C, le passage des paramètres se fait toujours par valeur,


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.
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.

V. V. Passage de paramètres à une fonction

Les paramètres ou arguments sont les boites à lettres d’une fonction.


Elles acceptent les données de l’extérieur et déterminent les actions
et le résultat de la fonction.

6
A l’intérieur de la fonction, On peut donc changer les valeurs des Valeur de compteur: 14
paramètres sans influencer les valeurs originales dans les fonctions la valeur de compteur n’a donc pas été modifié par l’appel de la
appelantes. fonctionETOILES.

Exemple : b) Passage des paramètres par adresse


La fonction ETOILES dessine une ligne de N étoiles. Le paramètre
N est modifié à l’intérieur de la fonction mais pas à l’extérieur: Comme on vient de le voir, touts les paramètres passent par valeur,
et cette règle n’offre aucune exception. Cela pose le problème de
#include<stdio.h>void réaliser un passage de paramètre par adresse lorsque le programmeur
ETOILES(int N) { en a besoin.
while (N>0) { Pour changer la valeur d’une variable de la fonction appelante, on
printf("*"); procède comme suite :
N--; – la fonction appelante doit fournir l’adresse de la variable;
} – la fonction appelée doit déclarer le paramètre comme pointeur.
printf("\n"); On peut alors atteindre la variable à l’aide du pointeur.
}
Int main() { Exemple: Supposons qu’on désire écrire une fonction add,
int compteur=14; admettant trois paramètres a, b et c. On désire que le résultat de
ETOILES(compteur); l’exécution de add soit d’affecter au paramètre c, la somme des
printf("Valeur de compteur: %i\n",compteur); valeurs des deux premiers paramètres.
return 0; Le paramètre c ne peut évidemment pas être passé par valeur,
} puisqu’on désire modifier la valeur du paramètre effectif
correspondant. Il faut donc programmer add de la manière suivante :
L’appel de ce programme renvoit :
**************

7
#include<stdlib.h>
void add(int a, int b, int*c) /* Initialise les éléments d’un tableau */
{ /* c repère l’entier où on veut mettre le résultat*/ void init_tab (int tab[], int n){
*c = a +b; int i;
} for (i = 0; i< n; i++)
tab[i] = i;
int main() { return;
int i=10, j=14, k; }
/* on passe les valeurs de i et j comme premiers paramètres*/ int main() {
/* on passe l’adresse de k comme troisième paramètre */ Rappelons qu’un tableau est un pointeur constant (sur le premier
add(i,j,&k); élément du tableau)
}
int i, n =5;
c) Passage de tableau en paramètre int *tab;
Comme il est impossible de passer la valeur de tout un tableau à tab = (int*)malloc(n * sizeof(int));
une fonction, on fournit l’adresse d’un l’élément du tableau. init (tab,n);
En général, on fournit l’adresse du premier élément du tableau, qui }
est donnée par le nom du tableau.
Dans la liste des paramètres d’une fonction, on peut déclarer un VI.Pointeurs sur une fonction
tableau par le nom suivi de crochets, <type><nom>[] ou
simplement par un pointeur sur le type des éléments du tableau : Il est parfois utile de passer une fonction comme paramètre d’une
<type> *<nom> autre fonction. Cette procédure permet en particulier d’utiliser une
même fonction pour différents usages. Pour cela, on utilise un
Exemple : mécanisme de pointeur.

8
Un pointeur sur une fonction correspond à l’adresse du début du de la fonction operateur_binaire, on écrit (*f)(a, b). Ainsi, cette
code de la fonction. Un pointeur p_fonction sur une fonction ayant fonction pourrait s’´ecrire : int operateur_binaire(int a, int b, int
pour prototype type fonction (type_1 arg_1,...,type_n arg_n); se (*f)(int, int)) {
déclare par : type(*p_fonction)(type_1,...,type_n); return((*f)(a,b));

Ainsi, considérons une fonction operateur_binaire prenant pour


paramètres deux entiers a et b, ainsi qu’une fonction f de type int
qui prend elle-même deux entiers en paramètres. On suppose que
operateur_binaire renvoit l’entier f(a,b).
Le prototype de cette fonction sera : int operateur_binaire(int a, int
b, int (*f)(int,int))

Pour appeler la fonction operateur_binaire, on utilisera comme


troisième paramètre effectif l’identificateur de la fonction utilisée.
Par exemple, si somme est la fonction int somme(int a, int b) {
return a+b;}
on appelle la fonction operateur_binaire pour la fonction somme par
l’expression :
operateur_binaire(a,b,somme)
A noter que la notation &somme n’est pas utilisée comme paramètre
effectif. Pour appeler la fonction passée en paramètre dans le corps

9
10

Vous aimerez peut-être aussi