print · rss · source

< Les itérations | TutoCFrench | Portée des données au sein d'un programme >


Les fonctions

Notions :

  • déclaration
  • prototype
  • arguments
  • valeur renvoyée
  • return
  • void
  • passage par valeur

Qu'est-ce qu'une fonction ?

  • Une fonction peut être vue comme un bloc d'instructions avec un nom. A chaque fois que l'on souhaite refaire ces instructions, plutôt que de les recopier, il suffit de les invoquer par le nom de la fonction. Une fonction peut alors être vue comme un racourcis d'écriture.
  • Mais une fonction peut aussi être vue comme un "outil" pratique auquel on peut faire appel sans se soucier de la façon dont il a été écrit. Nous avons déjà utilisé de cette façon les fonctions printf() et scanf().
  • Une fonction peut prendre des arguments. C'est ce qui permet de moduler son fonctionnement selon nos besoins et c'est d'ailleurs de cette façon que nous avons utilisé printf() et scanf().
  • Une fonction peut retourner une valeur. C'est le cas, par exemple, des fonctions mathématiques.

Un premier exemple

Nous avons vu dans la leçon précédente comment afficher plusieurs fois une lettre. Il peut être très pratique de créer une fonction si nous avons besoin de répéter plusieurs fois cette opération :

#include <stdio.h>

void repete_car(char c, int n)
{
    int i;
    for (i=0;i<n;i++)
        printf("%c", c);
    printf("\n");
    return;
}

int main()
{
    repete_car('a', 5);
    repete_car('b', 12);
    repete_car('c', 1);
    return 0;
}

Ce programme n'est pas bien compliqué et toutes les nouvelles notions nécessaires à sa compréhension sont expliquées ci-dessous.

Créer et utiliser une fonction

Une fonction est définie de la façon suivante :

type nom(type var1, type var2, ..., type varn)
{
declarations;
instruction;
...
instruction;
return valeur;
}

Quelques explications :

  • type nom... indique le nom de la fonction et le type de valeur renvoyée par la fonction
  • (type var1,...) indique le type et le nom des arguments passés en paramètre et utilisés dans le corps de la fonctions
  • { débute le code de la fonction
  • Ensuite une ou plusieurs lignes permettent de déclarer des variables utilisées dans le corps de la fonctions
  • Le code proprement dit
  • L'instruction return termine une fonction en renvoyant éventuellement une valeur
  • } termine la définition du code de la fonction

Par exemple, la fonctions suivante prend en argument deux entiers et renvoie leur somme :

#include <stdio.h>

int addition(int a, int b)
{
    int c;
    c = a + b;
    return c;
}

int main()
{
    int x;
    x = addition(2,5);
    printf("%d", x);
    return 0;
}

L'appel à la fonction addition fonctionne en plusieurs étapes :

  1. Dans la fonction principale main(), on fait appel à la fonction addition qui prend en argument deux entiers, ici 2 et 5
  2. Ces valeurs sont copiées dans les variables a et b définies dans l'en-tête de la fonction
  3. La fonction calcule la valeur de c
  4. La fonction retourne la valeur de c
  5. On revient dans la fonction main() à l'endroit où la fonction addition avait été appelée. La fonction est évaluée en lui substituant la valeur qu'elle retourne. Cette valeur est alors affectée à x.

Déclaration

Si une fonction est définie dans le code source avant la portion de code qui l'utilise, il n'est pas besoin de la déclarer. Dans le cas contraire il faut la déclarer en mettant son prototype dans l'entête du programme.
Le prototype d'une fonction indique le nombre et le type de ses arguments et le type de donnée renvoyé :

int addition(int, int);

Par exemple :

#include <stdio.h>

int addition(int, int); /* declaration */

int main()
{
    int x;
    x = addition(2,5);
    printf("%d", x);
    return 0;
}

int addition(int a, int b) /* definition */
{
    int c;
    c = a + b;
    return c;
}

Comprendre la notion de valeur retournée

L'instruction return, qui termine une fonction, permet de retourner une valeur. Une fonction se comporte alors comme une expression qui est évaluée puis remplacée par sa valeur. Par exemple, dans le programme suivant, l'appel à la fonction addition est tout à fait autorisé au sein d'une expression mathématique ou dans une fonction :

#include<stdio.h>
int addition(int, int);

int main()
{
    int x=1, y=2, z;

    /* on affecte a 'z' la valeur retournee par la fonction */
    z = addition(x+y);

    /* possible aussi */
    printf("%d\n", addition(x+y) );

    /* egalement possible ! */
    z = addition(addition(x+3),5);

    return 0;
}

int addition(int a, int b)
{
    return (a+b);
}

Le type void

On peut souhaiter créer une fonction qui ne prend aucun argument et/ou qui ne renvoie pas de valeur. En C, void est un type spécial qui signifie "rien". Il est utilisable à la place des arguments et de la valeur renvoyée. Par exemple, sous Unix, il existe une fonction rand() qui sert à générer un nombre au hasard et dont le prototype est le suivant :

int rand(void);

Cette fonction ne prend aucun argument (type void) et renvoie un entier (type int).
Les fonctions qui ne renvoient aucune valeur sont plus rares. La fonction suivante ne prend pas d'argument, ne renvoie aucune valeur, et se contente d'afficher un message standard :

void afficher_menu(void) {
    printf("(p)oisson, (v)iande rouge ou (p)oulet ?\n");
    printf("choix> ");
    return;
}

Comprendre le passage par valeur

Une fonction ne prend en argument que des valeurs. C'est à dire que si on passe une variable en argument à une fonction, on ne passe pas en argument la variable elle-même mais une copie de sa valeur. Cela a une implication essentielle : une fonction ne permet pas de modifier directement une variable ! Par exemple, dans le programme suivant, la fonction ne modifie pas la valeur de a :

#include<stdio.h>

void incr(int x)
{
    x++;
}

int main()
{
    int a = 1;

    incr(a);
    /* 'a' n'est pas modifie ! */

    printf("%d", a);  /* affiche 1 */
    return 0;
}

Quelques erreurs courantes

Oublier de déclarer les noms de variables dans la définition d'une fonction :
int addition(int, int) /* oh, on a oublie les noms de variables ! */
{
    int c;
    c = a+b;
    return c;
}
Mettre des ; en trop :
int addition(int a, int b);     /* il y a un ';' en trop !!! */
{
    return a+b;
}
Redéclarer les noms de variables :
int addition(int a, int b)
{
    int a, b;       /*  variables deja declarees dans l'en-tete de la fonction */
    return a+b;
}
Oublier de retourner une valeur :
int addition(int a, int b)
{
    int c;
    c = a + b;
    return; /* on oublie de retourner un entier ! */
}

Exercices

1. "puis.c" : créer une fonction qui prend deux arguments et qui renvoie le premier nombre puissance le second
2. "fact.c" : programme qui calcule la factorielle d'un nombre saisi. On utilisera deux méthodes différentes (itération et récursion). Rappel : fact(n) = n * (n-1) * ... * 3 * 2 * 1
3. "pyra.c" : programme qui trace une pyramide. Le nombre de niveaux est saisi par l'utilisateur :

$ pyra
> 4
   ^
  ^^^
 ^^^^^
^^^^^^^
> 2
 ^
^^^

Solutions

puis.c

#include <stdio.h>

int puis(int n, int exp)
{
    int total = 1;
    while(exp--)
        total *= n;
    return total;
}

int main()
{
    int a, b;

    scanf("%d %d", &a, &b); 
    printf("%d\n", puis(a, b));

    return 0;
}

fact.c par la méthode itérative

#include <stdio.h>

int fact(int n)
{
    int total = n;
    while (--n > 0)
        total *= n;
    return total;
}

int main()
{
    int a;

    scanf("%d", &a);
    printf("%d\n", fact(a));

    return 0;
}

fact.c par la méthode récursive

#include <stdio.h>

int fact(int n)
{
    return (n>1) ? n * fact(n-1) : n;
}

int main()
{
    int a;

    scanf("%d", &a);
    printf("%d\n", fact(a));

    return 0;
}

pyra.c

#include <stdio.h>

void pyra(int n)
{
    int i, j, k;
    for (i=0; i<n; i++) {
        for (j=0; j<(n-i-1); j++)
            printf(" ");
        for (k=0; k<i*2+1; k++)
            printf("^");
        printf("\n");
    }
    return;
}

int main()
{
    int a;

    scanf("%d", &a);
    pyra(a);

    return 0;
}

< Les itérations | TutoCFrench | Portée des données au sein d'un programme >

print · rss · source
Page last modified on March 22, 2008, at 03:34 PM