1 of 33

Chapitre 7

2011/2012

Les fonctions

2 of 33

La programmation modulaire

2011/2012

2

  • Certains problèmes conduisent à des programmes longs, difficiles à écrire et à comprendre. On les découpe en des parties appelées sous-programmes ou modules
  • Les modules sont des groupes d'instructions qui fournissent une solution à des parties bien définies d'un problème plus complexe. Ils ont plusieurs intérêts :

    • permettent de "factoriser" les programmes, càd de mettre en commun les parties qui se répètent
    • permettent une structuration et une meilleure lisibilité des programmes
    • facilitent la maintenance du code (il suffit de modifier une seule fois)
    • peuvent éventuellement être réutilisées dans d'autres programmes
  • La structuration de programmes en sous-programmes se fait en C à l'aide des

fonctions

3 of 33

Fonctions

2011/2012

3

  • On définit une fonction en dehors de la fonction principale main ( ) par :

type nom_fonction (type1 arg1,…, typeN argN)

{

instructions constituant le corps de la fonction return (expression)

}

  • Dans la première ligne (appelée en-tête de la fonction) :
    • type est le type du résultat retourné. Si la fonction n’a pas de résultat à retourner, elle est de type void.
    • le choix d'un nom de fonction doit respecter les mêmes règles que celles adoptées pour les noms de variables.
    • entre parenthèses, on spécifie les arguments de la fonction et leurs types. Si une fonction n'a pas de paramètres, on peut déclarer la liste des paramètres comme (void) ou simplement comme ()
  • Pour fournir un résultat en quittant une fonction, on dispose de la commande

return.

4 of 33

Fonctions : exemples

  • Une fonction qui calcule la somme de deux réels x et y :
  • double Som(double x, double y )
  • {
  • return (x+y);
  • }

  • Une fonction qui affiche la somme de deux réels x et y :
  • void AfficheSom(double x, double y)
  • {
  • printf (" %lf", x+y );
  • }
  • Une fonction qui renvoie un entier saisi au clavier
  • int RenvoieEntier( void )
  • {
  • int n;
  • printf (" Entrez n \n"); scanf (" %d ", &n); return n;
  • }
  • Une fonction qui affiche les éléments d’un tableau d’entiers
  • void AfficheTab(int T[ ], int n)
  • { int i;
  • for(i=0;i<n;i++) printf (" %d \t", T[i]);
  • }

2011/2012

4

5 of 33

Appel d’une fonction

2011/2012

5

  • L‘appel d'une fonction se fait par simple écriture de son nom avec la liste des paramètres : nom_fonction (para1,…, paraN)
  • Lors de l'appel d'une fonction, les paramètres sont appelés paramètres effectifs : ils contiennent les valeurs pour effectuer le traitement. Lors de la définition, les paramètres sont appelés paramètres formels.
  • L'ordre et les types des paramètres effectifs doivent correspondre à ceux des paramètres formels

  • Exemple d’appels: main( )

{ double z;

int A[5] = {1, 2, 3, 4, 5};

z=Som(2.5, 7.3);

AfficheTab(A,5);

}

6 of 33

Déclaration des fonctions

2011/2012

6

  • Il est nécessaire pour le compilateur de connaître la définition d'une fonction au moment où elle est appelée. Si une fonction est définie après son premier appel (en particulier si elle définie après main ), elle doit être déclarée auparavant.

  • La déclaration d'une fonction se fait par son prototype qui indique les types de ses paramètres et celui de la fonction :

type nom_fonction (type1,…, typeN)

  • Il est interdit en C de définir des fonctions à l'intérieur d'autres fonctions. En particulier, on doit définir les fonctions soit avant, soit après la fonction principale main.

7 of 33

Déclaration des fonctions : exemple

2011/2012

7

#include<stdio.h>

float ValeurAbsolue(float); //prototype de la fonction ValeurAbsolue

main( )

{ float x=-5.7,y;

y= ValeurAbsolue(x);

printf("La valeur absolue de %f est : %f \n " , x,y);

}

//Définition de la fonction ValeurAbsolue

float ValeurAbsolue(float a)

{

if (a<0) a=-a; return a;

}

8 of 33

Variables locales et globales

2011/2012

8

  • On peut manipuler 2 types de variables dans un programme C : des variables locales et des variables globales. Elles se distinguent par ce qu'on appelle leur portée (leur "espace de visibilité", leur "durée de vie")

  • Une variable définie à l'intérieur d’une fonction est une variable locale, elle n’est connue qu'à l'intérieur de cette fonction. Elle est créée à l'appel de la fonction et détruite à la fin de son exécution

  • Une variable définie à l’extérieur des fonctions est une variable globale. Elle est définie durant toute l’application et peut être utilisée et modifiée par les différentes fonctions du programme.

9 of 33

Variables locales et globales : remarques

2011/2012

9

  • Les variables déclarées au début de la fonction principale main ne sont pas des variables globales, mais elles sont locales à main

  • Une variable locale cache la variable globale qui a le même nom

  • Il faut utiliser autant que possible des variables locales. Ceci permet d'économiser la mémoire et d'assurer l'indépendance de la fonction

  • En C, une variable déclarée dans un bloc d'instructions est uniquement visible à l'intérieur de ce bloc. C’est une variable locale à ce bloc, elle cache toutes les variables du même nom des blocs qui l'entourent

10 of 33

Variables locales et globales : exemple

2011/2012

10

#include<stdio.h> int x = 7;

int f(int); int g(int); main( )

{ printf("x = %d\t", x);

{ int x = 6; printf("x = %d\t", x); }

printf("f(%d) = %d\t", x, f(x));

printf("g(%d) = %d\t", x, g(x));

}

int f(int a) { int x = 9; return (a + x); }

int g(int a) { return (a * x); } Qu’affiche ce programme?

x=7

x=6 f(7)=16

g(7) = 49

11 of 33

Variables locales et globales : exemple

2011/2012

11

#include<stdio.h> void f(void);

int i; main( )

{ int k = 5; i=3; f(); f();

printf("i = %d et k=%d \n", i,k); } void f(void) { int k = 1;

printf("i = %d et k=%d \n", i,k); i++;k++;}

Qu’affiche ce programme?

i=3 et k=1 i=4 et k=1 i=5 et k=5

12 of 33

  • La fonction main peut également posséder des paramètres formels.
  • un programme C peut recevoir une liste d’arguments au lancement de son exécution.
  • La ligne de commande qui sert à lancer le programme est, dans ce cas, composée du nom du fichier exécutable suivi par des paramétres.

2011/2012

13 of 33

  • la fonction main possède deux paramètres formels, appelés par convention:

argc (argument count)

argv (argument vector).

2011/2012

14 of 33

  • argc est une variable de type int dont la valeur est égale au nombre de mots composant la ligne de commande (y compris le nom de l’exécutable). Elle est donc égale au nombre de paramètres effectifs de la fonction + 1.

2011/2012

15 of 33

  • argv est un tableau de chaînes de caractères correspondant chacune à un mot de la ligne de commande. Le premier élément argv[0] contient donc le nom de la commande (du fichier exécutable), le second argv[1] contient le premier paramètre. . . .

  • int main ( int argc, char *argv[]);

2011/2012

16 of 33

  • #include <stdio.h> // exemple1.c
  • #include <stdlib.h> //gcc -o test exemple1.c

  • int main(int argc, char *argv[])
  • { int a, b;
  • if (argc != 3)
  • {
  • printf("\nErreur : nombre invalide d’arguments");
  • printf("\nUsage: %s int int\n",argv[0]);
  • return(EXIT_FAILURE);
  • }
  • a = atoi(argv[1]);
  • b = atoi(argv[2]);
  • printf("\nLe produit de %d par %d vaut : %d\n", a, b, a * b);
  • return(EXIT_SUCCESS); }

2011/2012

17 of 33

  • On lance donc l’exécutable avec deux paramètres entiers, par exemple,

test 2 8

  • Ici, argv sera un tableau de 3 chaînes de caractères argv[0], argv[1] et argv[2]

argv[0]=" test", argv[1]= "2" et argv[2] ="8".

  • la fonction de la librairie standard atoi(), déclarée dans stdlib.h, prend en argument une chaine de caractères et retourne l’entier dont elle est l’écriture décimale.

2011/2012

18 of 33

Paramètres d'une fonction

2011/2012

18

  • Les paramètres servent à échanger des informations entre la fonction appelante et la fonction appelée. Ils peuvent recevoir des données et stocker des résultats

  • Il existe deux modes de transmission de paramètres dans les langages de programmation :
    • La transmission par valeur : les valeurs des paramètres effectifs sont affectées aux paramètres formels correspondants au moment de l'appel de la fonction ou procédure. Dans ce mode le paramètre effectif ne subit aucune modification
    • La transmission par adresse (ou par référence) : les adresses des paramètres effectifs sont transmises à la fonction appelante. Dans ce mode, le paramètre effectif subit les mêmes modifications que le paramètre formel

19 of 33

Transmission des paramètres en C

2011/2012

19

  • La transmission des paramètres en C se fait toujours par valeur
  • Pour effectuer une transmission par adresse en C, on déclare le paramètre formel de type pointeur et lors d'un appel de la fonction, on envoie l'adresse et non la valeur du paramètre effectif
  • Exemple : void Increment (int x, int *y)

{ x=x+1;

*y =*y+1; } main( )

{ int n = 3, m=3; Increment (n, &m);

printf(“n = %d et m=%d \n", n,m); }

Résultat :

n=3 et m= 4

20 of 33

Exemples

2011/2012

20

Une fonction qui échange le contenu de deux variables : void Echange (float *x, float *y)

{ float z;

z = *x;

*x = *y;

*y = z;

}

main()

{ float a=2,b=5; Echange(&a,&b); printf("a=%f,b=%f\n ",a,b);

}

21 of 33

Récursivité

2011/2012

21

  • Une fonction qui fait appel à elle-même est une fonction récursive

  • Toute fonction récursive doit posséder un cas limite (cas trivial) qui arrête la récursivité
  • Exemple : Calcul du factorielle

int fact (int n )

{ if (n==0)

/*cas trivial*/

return (1);

else

return (n* fact(n-1) );

}

Remarque : l’ordre de calcul est l’ordre inverse de l’appel de la fonction

22 of 33

Fonctions récursives : exercice

2011/2012

22

  • Ecrivez une fonction récursive (puis itérative) qui calcule le terme n

de la suite de Fibonacci définie par :

U(0)=U(1)=1 U(n)=U(n-1)+U(n-2)

int Fib (int n)

{

if (n==0 || n==1)

return (1);

else

return ( Fib(n-1)+Fib(n-2));

}

23 of 33

Fonctions récursives : exercice (suite)

2011/2012

23

  • Une fonction itérative pour le calcul de la suite de Fibonacci :

int Fib (int n)

{ int i, AvantDernier, Dernier, Nouveau; if (n==0 || n==1) return (1); AvantDernier=1; Dernier =1;

for (i=2; i<=n; i++)

{ Nouveau= Dernier+ AvantDernier; AvantDernier = Dernier;

Dernier = Nouveau;

}

return (Nouveau);

}

Remarque: la solution récursive est plus facile à écrire

24 of 33

Chapitre 8

2011/2012

Les Chaînes de caractères

25 of 33

Chaînes de caractères

2011/2012

25

  • Il n'existe pas de type spécial chaîne ou string en C. Une chaîne de caractères est traitée comme un tableau de caractères

  • Une chaîne de caractères en C est caractérisée par le fait que le dernier élément vaut le caractère ‘\0’, ceci permet de détecter la fin de la chaîne

  • Il existe plusieurs fonctions prédéfinies pour le traitement des chaînes de caractères (ou tableaux de caractères )

26 of 33

Déclaration

2011/2012

26

  • Syntaxe : char <NomVariable> [<Longueur>]; //tableau de caractères

Exemple : char NOM [15];

  • Pour une chaîne de N caractères, on a besoin de N+1 octets en mémoire (le dernier octet est réservé pour le caractère ‘\0’)

  • Le nom d’une chaîne de caractères est le représentant de l’adresse du 1er caractère de la chaîne

  • On peut aussi manipuler les chaînes de caractères en utilisant des pointeurs (de la même façon qu'un pointeur sur int peut contenir l'adresse d'un élément d'un tableau d’entiers, un pointeur sur char peut pointer sur les éléments d'un tableau de caractères)

27 of 33

Initialisation

2011/2012

27

  • On peut initialiser une chaîne de caractères à la définition :

    • comme un tableau, par exemple : char ch[ ] = {‘e’,’c’,’o’,’l’,’e’,’\0’}
    • par une chaîne constante, par exemple : char ch[ ] = "école“
    • en attribuant l'adresse d'une chaîne de caractères constante à un pointeur sur char, par exemple : char *ch = "école“

  • On peut préciser le nombre d'octets à réserver à condition que celui-ci soit supérieur ou égal à la longueur de la chaîne d'initialisation

    • char ch[ 6] = "école“ est valide
    • char ch[ 4] = "école“ ou char ch[ 5] = "école“ provoque une erreur

28 of 33

Traitement des chaînes de caractères

2011/2012

28

  • Le langage C dispose d’un ensemble de bibliothèques qui contiennent des fonctions spéciales pour le traitement de chaînes de caractères

  • Les principales bibliothèques sont :

    • La bibliothèque <stdio.h>
    • La bibliothèque <string.h>
    • La bibliothèque <stdlib.h>

  • Nous verrons les fonctions les plus utilisées de ces bibliothèques

29 of 33

Fonctions de la bibliothèque <stdio.h>

2011/2012

29

  • printf( ) : permet d’afficher une chaîne de caractères en utilisant le spécificateur de format %s.

Exemple : char ch[ ]= " Bonsoir " ;

printf(" %s ", ch);

  • puts( <chaine>) : affiche la chaîne de caractères désignée par

<Chaîne> et provoque un retour à la ligne.

Exemple : char *ch= " Bonsoir " ;

puts(ch); /*équivalente à printf("%s\n ", ch);*/

30 of 33

Fonctions de la bibliothèque <stdio.h>

2011/2012

30

  • scanf( ) : permet de saisir une chaîne de caractères en utilisant le spécificateur de format %s.

Exemple : char Nom[15];

printf("entrez votre nom");

scanf(" %s ", Nom);

Remarque : le nom d'une chaîne de caractères est le représentant de l'adresse du premier caractère de la chaîne, il ne doit pas être précédé de &

  • gets( <chaine>) : lit la chaîne de caractères désignée par <Chaîne>

Exemple : char phrase[100];

printf("entrez une phrase"); gets(phrase);

31 of 33

Fonctions de la bibliothèque <string.h>

2011/2012

31

  • strlen(ch): fournit la longueur de la chaîne sans compter le '\0' final Exemple : char s[ ]= " Test";

printf(“%d”,strlen(s)); //affiche 4

  • strcat(ch1, ch2) : ajoute ch2 à la fin de ch1. Le caractère ‘\0’ de ch1 est écrasé par le 1er caractère de ch2

Exemple : char ch1[20]=" Bonne ", *ch2=" chance ";

strcat(ch1, ch2) ;

printf(" %s", ch1); // affiche Bonne chance

32 of 33

Fonctions de la bibliothèque <string.h>

2011/2012

32

  • strcmp(ch1, ch2): compare ch1 et ch2 lexicographiquement et retourne une valeur : - nul si ch1 et ch2 sont identiques
    • négative si ch1 précède ch2
    • positive si ch1 suit ch2

  • strcpy(ch1, ch2) : copie ch2 dans ch1 y compris le caractère ‘\0’

Exemple : char ch[10];

strcpy(ch, " Bonjour ");

puts(ch); // affiche Bonjour

  • strchr(char *s, char c) : recherche la 1ère occurrence du caractère c dans la chaîne s et retourne un pointeur sur cette 1ère occurrence si c’est un caractère de s, sinon le pointeur NULL

33 of 33

Fonctions de la bibliothèque <stdlib.h>

2011/2012

33

<stdlib> contient des fonctions pour la conversion de nombres en chaînes de caractères et vice-versa.

  • atoi(ch): retourne la valeur numérique représentée par ch comme int
  • atof(ch): retourne la valeur numérique représentée par ch comme float

(si aucun caractère n’est valide, ces fonctions retournent 0) Exemple : int x, float y;

char *s= " 123 ", ch[]= " 4.56 "; x=atoi(s); y=atof(ch); // x=123 et y=4.56

  • itoa(int n, char * ch, int b) : convertit l’entier n en une chaîne de caractères qui sera attribué à ch. La conversion se fait en base b

Exemple : char ch[30]; int p=18;

itoa(p, ch, 2); // ch= " 10010 ";