La programmation modulaire
Fonctions récursives
CHAPITRE 8 : Fonctions
8.1 La programmation modulaire
Consiste à découper un programme en plusieurs parties appelées modules :
Un module est une entité de données et d'instructions fournissant une solution à
une partie bien définie d'un problème plus complexe.
Un module peut faire appel à d'autres modules, leur transmettre des données et
recevoir des données en retour.
L'ensemble des modules reliés doit résoudre le problème global.
Pourquoi la programmation modulaire ? :
Un programme sur plusieurs pages devient difficile à comprendre et à maîtriser.
Il faut souvent répéter les mêmes instructions dans le texte du programme, ce qui
entraîne un gaspillage de la mémoire.
Un module, une fois mis au point, peut être réutilisé par d'autres modules ou
programmes (notion de réutilisation du code)
Un module peut être changé ou remplacé sans devoir toucher aux autres modules
du programme.
…
En C, la structuration d'un programme en sous-programmes (modules) se
fait à l'aide de fonctions.
1
CHAPITRE 8 : Fonctions
8.2 Définition, appel et dé
déclaration d’
d’une fonction
8.2.1 Définition d'une fonction
Une fonction est définie par un entête et un corps contenant les instructions à
exécuter :
type nom_fonction ( type_1 arg_1 , ... , type_n arg_n )
{
déclarations de variables locales
liste d'instructions
}
La première ligne de cette définition est l'en-tête de la fonction. Dans cet en-tête, type
désigne le type de la fonction, c'est-a-dire le type de la valeur qu'elle retourne. Une fonction
qui ne renvoie pas de valeur est une fonction dont le type est spécifié par le mot clef void.
Les arguments de la fonction, appelés paramètres formels, peuvent être de n'importe
quel type. Enfin, si la fonction ne possède pas de paramètres, on remplace la liste de
paramètres par le mot clef void.
Le corps de la fonction débute éventuellement par des déclarations de variables, qui sont
locales à cette fonction. Il se termine par l'instruction de retour à la fonction appelante,
return, dont la syntaxe est return expression ;
CHAPITRE 8 : Fonctions
8.2 Définition, dé
déclaration et appel d’
d’une fonction 8.2.1 Définition d'une fonction :
void affiche_bonjour(void )
Exemples : {
printf("Bonjour tout le monde \n");
Écrire : }
une fonction, nommée affiche_bonjour, se contentant
d’afficher « Bonjour tout le monde » (elle ne possède void affiche_somme(short a, short b)
aucun argument ni valeur de retour). {
printf("%d",a+b);
Une fonction, nommée affiche_somme, qui affiche la }
somme de deux entiers (short) passés comme paramètres
(elle ne possède aucune valeur de retour).
int produit(int a, int b)
{
Une fonction, nommée produit, qui reçoit en paramètre
return(a*b);
deux entiers (int) et retourne leur produit.
}
Une fonction, nommée imprime_tab, qui affiche les
éléments d’un tableau de réels (float). Le tableau ainsi void imprime_tab(float tab[], int nb_elements)
que le nombre d’éléments du tableau sont les paramètres {
de la fonction (elle ne possède aucune valeur de retour). int i;
for (i = 0; i < nb_elements; i++)
printf("%d \t",tab[i]);
printf("\n");
}
2
CHAPITRE 8 : Fonctions
8.2 Dé
Définition, dé
déclaration et appel d’
d’une fonction
CHAPITRE 8 : Fonctions
8.2 Définition, dé
déclaration et appel d’
d’une fonction 8.2.1 Appel d'une fonction :
Exemple :
Écrire une fonction, nommée puissance, qui calcule et retourne la valeur de xn
(double). Elle possède comme arguments x (double) et n (int).
#include<stdio.h>
double puissance(int n, double x)
{
double p = 1.0 ; // variable locale
for( i = 1 ; i <= n ; i++ ) p *= x ;
return p ; // valeur retournée
}
void main()
{
double y , z;
scanf("%lf",&z); // appel de scanf définie dans <stdio.h >
y = puissance(3, z+1.0) ; // appel de la fonction power
printf("(%lf+1)^3 = %lf", z , y ); // appel de printf définie dans <stdio.h>
}
3
CHAPITRE 8 : Fonctions
8.2 Dé
Définition, dé
déclaration et appel d’
d’une fonction
Une fonction secondaire est déclare par son prototype, qui donne le type de la
fonction et celui de ses paramètres, sous la forme :
CHAPITRE 8 : Fonctions
8.2 Définition, dé
déclaration et appel d’
d’une fonction 8.2.2 Déclaration d'une fonction :
Exemple :
#include <stdio.h>
void main()
{ int a = 2, b = 5;
printf("%ld\n", puissance( a , b ) ); //On affiche ab
}
4
CHAPITRE 8 : Fonctions
1. toute variable définie à l’extérieur des fonctions, d’un fichier source, est une
variable globale : elle est connue et utilisable partout dans n’importe quelle
fonction de ce fichier (sauf si elle est masquée par une variable locale). Elle
est allouée dans la zone d’allocation statique(segment de données).
2. toute variable définie à l’intérieur d’une fonction est une variable locale. Elle
n’est connue qu’à l’intérieur de la fonction dans laquelle elle est définie. Son
contenu est perdu d’un appel à l’autre de la fonction. Elle est allouée dans le
segment pile. Une variable locale cache la variable globale ayant même
nom.
CHAPITRE 8 : Fonctions
8.3 Durée de vie des variables
Exemple (variables locale & globale) :
#include <stdio.h> Affichage
void fct(void) //fonction prototype
int i; //variable globale
i : 3 *** k : 1
i : 4 *** k : 1
void main ( ) k de main : 5
{ int k = 5; //variable locale à main
i:5
i = 3;
fct();
fct(); •Il n’existe aucun lien entre la variable k de
printf ("k de main : %d \n", k ); main et la variable k de fct. Toute
printf ("i : %d \n", i ); modification de l’une n’a aucune influence
} sur l’autre.
•On peut avoir accès et modifier la variable i,
void fct(void) qui est globale, à, partir de main() et fct().
{ int k = 1 //variable locale à fct
•La variable k de fct() est réinitialisée à 1 lors
printf ("i : %d *** k : %d \n",i, k );
de chaque entrée dans fct().
i++; k++;
}
5
CHAPITRE 8 : Fonctions
8.4 Passage des paramètres d’une fonction
A l'appel d'une fonction avec paramètres, la valeur ou l'adresse du paramètre
effectif est transmise au paramètre formel correspondant.
CHAPITRE 8 : Fonctions
8.4 Passage des paramètres d’une fonction
Exemples (passage par valeur & passage par adresse):
Écrire un programme C qui saisie et affiche
#include <stdio.h> un tableau de N entiers en utilisant des fonctions.
void fct_val(int) //passage d’argument par valeur #include <stdio.h>
void fct_adr(int *) //passage d’argument par adresse void saisie_N( int *n )
void main( ) { printf("n (<=20) : ? " );scanf("%d",n);}
{ int i = 4 ;
fct_val( i ); void saisie_T( int T[ ] , int n)
printf("Après passage d’argument par valeur i : %d\n", i ); {int i ; for( i=0 ; i<n ; i++ ) scanf("%d",&T[i]);}
fct_adr( &i );
printf("Après passage d’argument par adresse i : %d\n", i ); void affichage_T( int T[ ] , int n)
} {int i ; for( i=0 ; i<n ; i++ ) printf("%d\t",T[i]);}
void fct_val(int a) { a = a + 3; }
void fct_adr(int *a) { *a = *a + 3; } int main( )
{ int T[20] , N;
Affichage saisie_N( &N );
Après passage d’argument par valeur i : 4 saisie_T( T , N );
affichage_T( T , N );
Après passage d’argument par adresse i : 7 return 0;
}
6
CHAPITRE 8 : Fonctions
8.5 Fonctions récursives
Une fonction est récursive si elle contient dans sa définition un appel à elle-même
L'ordre de calcul est l'ordre inverse de l'appel de la fonction.
Procédé pratique :
Pour trouver une solution récursive d'un problème, on cherche à le décomposer
en plusieurs sous-problèmes de même type, mais de taille inférieure. On procède de
la manière suivante :
Rechercher un cas trivial et sa solution (évaluation sans récursivité)
Décomposer le cas général en cas plus simples eux aussi décomposables pour aboutir au
cas trivial.
CHAPITRE 8 : Fonctions
8.5 Fonctions récursives
Exemples :