Il est fréquent, dans un programme, que l'on ait à réaliser en plusieurs endroits un travail comparable. Dans ces conditions, il est regrettable d'avoir à introduire, à diverses reprises, des instructions identiques ou presque. Le C, comme la plupart des langages, permet de réaliser des "sous-programmes". Il s'agit d'ensembles d'instructions qu'on écrit une seule fois en leur attribuant un nom. Ces ensembles sont appelés fonction.
Exemple :
#include <stdio.h>
float cube(float val); /* prototype de notre fonction cube */
main()
{
float a,c;
a=1.5;
c=cube(a); /* utilisation
de la fonction cube */
c=cube(a) * 3.0; /*
utilisation de cube dans une expression */
printf("cube de 2.2 est %f",
cube(2.2)); /* utilisation de cube dans une instruction
*/
}
float cube(float val) /* en-tête de la fonction
cube */
{
float y; /* variable
locale à la fonction cube */
y=val*val*val;
return y; /*
instruction qui renvoie la valeur du cube */
}
Le retour au programme appelant la fonction s'effectue grâce à l'instruction return. Cette instruction peut être employée sans paramètre si la fonction n'a pas de valeur de retour, ou avec un unique paramètre (si cela est nécessaire).
La syntaxe est :
return <expression>;
est aussi valable que
return(<expression>);
Exemples :
return; /*
retour au programme appelant sans valeur de retour */
return a;
/* la valeur contenue dans a est renvoyée en retour
*/
return (b);
/* la valeur contenue dans b est renvoyée en retour
*/
return (10);
/* la valeur 10 est renvoyée en retour */
Quand une fonction ne renvoie pas de résultats, on le précise, à la fois dans l'en-tête et dans sa déclaration, à l'aide du mot clé void. Par exemple, voici l'en-tête d'une fonction recevant un argument de type int et ne fournissant aucune valeur :
void sansval (int n)
et voici quelle serait son prototype
void sansval (int n);
Naturellement, la définition d'une telle fonction ne doit contenir aucune
instruction return.
Quand une fonction ne reçoit aucun argument, on place le mot clé void
(le même que précédemment, mais avec une signification différente), à la
place de la liste d'arguments. Voici l'en-tête d'une fonction ne recevant
aucun argument et renvoyant une valeur de type float :
float tirage (void)
Sa déclaration serait très voisine (elle ne diffère que par la présence du point-virgule) :
float tirage (void);
Enfin, rien n'empêche de réaliser une fonction ne possédant ni arguments ni valeur de retour. Dans ce cas, son en-tête sera de la forme :
void message (void)
et sa déclaration sera :
void message (void);
Voici un exemple illustrant deux des situations évoquées. Nous y définissons une fonction affiche_carres qui affiche les carrés des nombres entiers compris entre deux limites fournies en arguments et une fonction erreur qui se contente d'afficher un message d'erreur.
Exemple :
#include <stdio.h>
void affiche_carres
(int d, int f);
void erreur
(void);
main()
{
int
debut, fin;
printf("Entrez les deux limites : ");
scanf("%d%d", &debut, &fin);
if (debut<fin) affiche_carres (debut,
fin);
else erreur();
}
void affiche_carres
(int d, int f)
{
int i;
for (i=d;i<=f;i++)
printf("%d a pour carre %d\n",
i, i*i);
}
void erreur
(void)
{
printf("*** erreur ***\n");
}
La fonction main est paramétrable !
Supposons que l'exécution d'un programme soit lancée à l'aide d'une
commande quelconque : com.
Introduisons dans cette commande des paramètres effectifs :
com par_ef1 par_ef2 par_ef3
Ces paramètres effectifs qui sont des chaînes de caractères, pourront
être transmis à la fonction principale main
qui sera alors déclarée avec deux paramètres formels (quel que soit le
nombre de paramètres effectifs de la commande d'exécution) :
main (argc, argv)
argc et argv sont les identificateurs conventionnels que l'on utilise habituellement pour désigner ces deux paramètres formels. argc est une variable de type int qui sera égale au nombre de paramètres effectifs+1. Cet argument supplémentaire correspond au nom de la commande elle-même.
argv est un tableau de pointeurs pointant
vers des chaînes de caractères :
argv[0] pointe vers le nom de la commande (le nom du programme)
argv[1] pointe vers le premier paramètre effectif de la commande
argv[2] pointe vers le second paramètre effectif de la commande
...
argv[argc] à la valeur nulle
Le tableau de pointeurs disposera donc d'un nombre d'éléments égal au nombre de paramètres effectifs+2.
Exemple :
Ecrivons un programme permettant de calculer le produit de deux nombres entiers. Ces deux nombres seront introduits sous forme de paramètres effectifs de la commande.
Si cette commande s'appelle prod, on lancera : prod 17 36 par exemple et le programme renverra le produit de 17 par 36.
Le programme correspondant est :
#include<stdio.h>
main(int argc,
char *argv[])
{
int p;
if (argc==1)
{
printf("Syntaxe incorrecte : entrez \"prg nombre1
nombre2\"\n");
return;
}
p=atoi(argv[1])*atoi(argv[2]);
/* p est le produit des deux entiers issus des deux
chaînes */
printf("%s * %s = %d\n", argv[1],
argv[2], p);
}