• Aucun résultat trouvé

Programmation impérative et langage C. Fonctions

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation impérative et langage C. Fonctions"

Copied!
31
0
0

Texte intégral

(1)

Programmation

impérative et langage C

Fonctions

(2)

Valeur de retour

Type du résultat d’une fonction : void : pas de résultat (procédure)

scalaire : char, int, float, pointeur, etc.

structure

Ne peut pas être un tableau

en paramètre de la fonction (cf. plus loin) via une structure (contenant le tableau)

via un pointeur si création dynamique du tableau

dans la fonction

(3)

Portée des variables

Les variables déclarées dans une fonction sont

locales : elles ne sont connues qu’à l’intérieur de la fonction

Possibilité d’utiliser le même nom pour des variables différentes dans plusieurs fonctions sans interférence

Variable globale : variable déclarée à l’extérieur de toute fonction

En général déclarée au début du fichier source après les directives (#include et #define) du pré-processeur Accessible à toutes les fonctions

Si le même nom est utilisé pour une variable globale et

une variable locale : référence à la variable locale

(4)

Durée de vie des variables

Du début à la fin de l’exécution du programme : Variables globales

Variables locales de la fonction main

Pendant le temps d’exécution d’une fonction : Variables locales

… sauf si déclarées static , persistent alors jusqu’à la fin de l’exécution du programme

Depuis leur création jusqu’à leur destruction : Variables crées dynamiquement

Ne pas oublier de les détruire (libérer) avant la

perte du pointeur

(5)

Exemple

(6)

Passage des paramètres

De manière générale on distingue deux

façons de passer des paramètres à un sous- programme, une procédure ou une fonction :

passage par valeur :

La fonction reçoit la valeur du paramètre effectif

passage par variable :

La fonction a accès directement au paramètre

effectif

(7)

Passage des paramètres (2)

Passage par valeur :

La fonction reçoit la valeur du paramètre effectif

Permet des expressions comme paramètres effectifs : y = fonc(3, a+b) ;

Chaque paramètre formel correspond à une variable locale initialisée par la valeur du paramètre effectif Si le paramètre effectif correspond à une variable celle-ci n’est pas modifiée par la fonction

Passage par variable :

La fonction accède aux variables passées en argument

et peut ainsi les modifier

(8)

Exemple : valeur

i : paramètre formel x : paramètre effectif La variable locale i

est modifiée, mais pas

la variable x

(9)

Passage de paramètres en C

Le C n’autorise que le passage par valeur

Pour donner l’accès à une variable externe il faut utiliser un pointeur : Argument formel : pointeur

Argument effectif : adresse

int fonc (…, int *p, …) ; // déclaration y = fonc (…, &x, …) ; // appel

La valeur de l’adresse est passée à la fonction ce qui permet l’accès à la zone mémoire contenant la variable

Attention lorsqu’on passe un tableau c’est un pointeur qui est transmis : il est donc possible de modifier le tableau

int fonc (int tab[]) ; // déclaration int a[5] ;

y = fonc (a) ; // appel

(10)

Exemple : pointeur

i : paramètre formel

&x : paramètre effectif La variable x est

modifiée par la

fonction (donc x et y

identiques)

(11)

Exemple : tableau (code source)

t : paramètre formel

Les crochets [ ] indiquent au compilateur qu’il s’agit d’un tableau donc d’un pointeur

n : paramètre formel, ici permet de passer la

dimension du tableau

a : paramètre effectif, pas

de crochets (pointeur)

(12)

Exemple : tableau (exécution)

Dans la fonction

La variable n est initialisée à la valeur 5 et peut être modifiée

Le tableau t correspond au tableau a de la fonction main et peut aussi être modifié

Après l’appel seul le tableau a est modifié

Tableau "passé par variable" (comme si)

Dimension passée par valeur

(13)

Argument de type tableau

En-tête de fonction :

type identificateur (type a[80]) type identificateur (type a[]) type identificateur (type *a) Ces trois déclarations sont identiques Exemples d’appel :

int f (float *a) ;

float g (float b[10]) ; float v[10], m[25] ;

int k ;

k = f(v) ;

k = g(&m[2]) ;

(14)

Argument de type chaîne

Une chaîne de caractères est un tableau ! Ce qui vient d’être dit s’applique

Argument chaîne de caractères :

int f (char a[80]) int f (char a[]) int f (char *a)

char text1="essai", *text2 ;

f ("toto") ; f (text1) ;

text2 = "truc" ;

f (text2) ;

(15)

Tableaux à deux dimensions

Le paramètre formel ne peut être défini sous la forme

a[][] mais a[][nb_c]

ou a[nb_l][nb_c]

nb_c et nb_l doivent être des constantes.

Le compilateur doit connaître la seconde dimension

(longueur des lignes) pour calculer l’adresse relative au début du tableau

k = (i*nb_c)+j

(16)

Tableaux à deux dimensions (2)

Si fonction utilisable pour des matrices de dimensions différentes

Passer l’adresse du tableau et les deux dimensions

Calcul de la position relative des

éléments dans la fonction

Les deux appels

sont équivalents

(17)

Tableaux à deux dimensions (3)

Exécution :

(18)

Récursivité

Le langage C est dit récursif : il autorise une fonction à s’appeler elle-même (directement ou indirectement).

Exemple : factorielle d’un entier

n! = 1×2×…×(n-1)×n = (n-1)!×n ou fact(n) = n×fact(n-1)

avec 0! = 1 ou fact(0) = 1

On peut donc calculer de proche en proche, premier essai : int fact (int n)

{

return n*fact(n-1) ; }

Danger : empilement des appels infinis ⇒ ne pas oublier la

condition d’arrêt (ici n = 0)

(19)

Récursivité (2)

Le corps d’une fonction récursive comporte toujours (et dans l’ordre) : La condition d’arrêt

L’appel récursif

Ce qui nous donne pour factorielle : int fact (int n)

{

if (n == 0) return 1 ; return n*fact(n-1) ; }

Appels successifs (pour n=3) :

fact(3) → fact(2) → fact(1) → fact(0)

Attention : le cas n < 0 (au premier appel) n’est pas pris en

compte ici ⇒ à revoir !

(20)

Récursivité (3)

Décodage d’un entier en binaire Solution itérative :

Tant que n ≠ 0

division de n par 2 reste ⇒ 0 ou 1 Fin tant que

Si impression du reste dans la boucle : l’ordre des chiffres est inversé

Il faut mémoriser les restes successifs dans un tableau et les imprimer dans le bon ordre après la boucle

Solution récursive ?

(21)

Récursivité (4)

Version récursive

(22)

Récursivité (5)

Empilement des appels :

Appel # 1 → n = 12 Appel # 2 → n = 6 Appel # 3 → n = 3 Appel # 4 → n = 1

Appel # 5 → n = 0 Fini, aucune impression jusque là

Retour # 1 ⇒ appel # 4 → impression de 1 (reste de 1 ÷ 2) Retour # 2 ⇒ appel # 3 → impression de 1 (reste de 3÷2) Retour # 3 ⇒ appel # 2 → impression de 0 (reste de 6÷2) Retour # 4 ⇒ appel # 1 → impression de 0 (reste de 12 ÷ 2) Retour # 5 ⇒ retour au programme principal (main)

La pile (étudiée dans le cours Interface Matériel Logiciel) permet

l’impression des chiffres dans le bon ordre

(23)

Tours de Hanoï

Le jeu est composé de 3 poteaux et de N disques troués de différents rayons

Au départ, tous les disques sont empilés avec des rayons décroissants sur un poteau

Le but est de déplacer les disques vers un autre poteau en ne déplaçant qu’un disque à la fois

en ne mettant jamais un disque sur un autre disque plus

(24)

Tours de Hanoï (2)

Si une solution existe pour toute valeur de n, il est possible de décomposer le problème en trois étapes :

Déplacement de n-1 disques vers troisième poteau (ici de A

vers C) :

(25)

Tours de Hanoï (3)

Déplacement du dernier disque (ici de A vers B) :

(26)

Tours de Hanoï (4)

Déplacement des n-1 disques

Algorithme pour n disques :

déplacement de n-1 disques de A vers C déplacement d’un disque de A vers B déplacement de n-1 disques de C vers B

Appels récursifs avec au début n = N et arrêt si n = 0

(27)

Tours de Hanoï (5)

Cet algorithme se prête donc à une implémentation récursive :

(28)

Tours de Hanoï (5)

(29)

Argument de type fonction

Exemple calcul par dichotomie du zéro d’une fonction bornes de l’intervalle : a, b

fonction : f précision : eps

float (*f) (float) Le nom d’une fonction est aussi un pointeur (sur la première instruction)

Exemple d’appel :

r = dicho (0, 3.14, cos, 1.e-5) ;

(30)

Arguments de la fonction main

Les arguments de la fonction main permettent de récupérer

d’éventuels paramètres placés à la suite du nom de programme sur la ligne de commande

Syntaxe :

int main (int n, char *arg[]) n : nombre de paramètres

arg[] : tableau de pointeurs sur des chaînes de caractères arg[0] : nom du programme (n toujours ≥ 1)

arg[1] : premier paramètre

arg[2] : deuxième paramètre, etc.

Ligne de commande :

./toto param1 param2

(31)

Dernier exemple

Avec ce programme on peut constater que n_arg est toujours supérieur ou égal à 1

Le nom du programme est toujours présent

Références

Documents relatifs

A l'aide d'un test que l'on précisera, au seuil de risque de 5%, déterminer la valeur minimale de n qui permet au chercheur de conclure que les résultats avec le nouveau traitement

3- A l’aide de vos connaissances et des documents, développer un argumentaire pour convaincre l’agriculteur producteur de pommes de terre de fertiliser différemment

(2) Il est facile d’étendre les résultats obtenus au cas d’une variable qui n’est pas abso- lument continue mais dont la distribution possède pour tout ~ des

Université Paris-Dauphine Licence de Mathématiques Appliqués. Intégrale de Lebesgue et Probabilités

Montrer que f est solution d'une équation diérentielle linéaire sur D

• Déf: mode de passage de paramètre = lien qui existe entre le paramètre formel et le paramètre actuel.. • Normallement le choix du mode de passage se fait indépendamment pour

Montrer que F est de classe C ∞ sur R et vérie une équation diérentielle linéaire du second ordre..

Dans ce cas on « transforme » une des deux variables à l’aide d’une fonction pour obtenir un nouveau nuage qui aura la forme d’une droite. Exemple 12.5 (D’après