En C, il n'existe aucune commande spécifique pour faire communiquer le programme avec l'extérieur. On utilise des fonctions externes fournies par le système sur lequel le programme doit fonctionner.
La norme C impose que tous les compilateurs fournissent un certain nombre de fonctions standards dont le fonctionnement et les paramètres sont définis par la norme. Chaque système peut proposer ses propres fonctions spécifiques en plus des fonctions standards.
Dans ces fonctions standards, on trouve entre autre des fonctions de calcul mathématique (log, cos, sin, sqrt, etc.), des fonctions d'entrées/sorties (printf, fprintf, scanf, fscanf, getc, putc, etc.), des fonctions d'accès aux fichiers (fopen, fclose, fread, fwrite, etc.), des fonctions de manipulation de chaînes de caractères (strlen, strcpy, strcat, etc.) et des fonctions de gestion de la mémoire (malloc, free, calloc, etc.).
Sous UNIX, le système propose une page de manuel en ligne (via la commande
man
) pour chacune de ces fonctions. Cette page précise à chaque fois le
nom du fichier d'en-tête à inclure pour faire connaître au compilateur la
déclaration de la fonction ainsi que le nom de l'éventuelle bibliothèque
contenant sa définition. Si aucune bibliothèque n'est nécessaire, cela
signifie que la définition de cette fonction externe est présente dans la
bibliothèque C. Cette bibliothèque est mise automatiquement à disposition du
compilateur lors de l'édition des liens d'un programme.
Nous ne détaillerons pas toutes ces fonctions. Nous nous
focaliseront sur printf
, scanf
pour les
entrées/sorties et sur malloc
et free
pour
l'allocation de mémoire dynamique.
printf
est une fonction externe inclue dans la
bibliothèque de fonctions C standards. Elle permet d'afficher
à l'écran des informations provenant du programme.
Elle prend un nombre d'arguments variable. Son premier argument est une chaîne de caractères spécifiant le format d'affichage. Les arguments suivants sont les valeurs qu'il faudra afficher. C'est le contenu du format qui permet de dire comment les arguments suivants seront affichés :
Le format est interprété de la manière suivante :
%
sera remplacer à
l'affichage par la valeur d'un argument. Le caractère qui suit le %
précise le type de l'argument et la manière dont il sera affiché (tableau 9.1).
La première séquence sera remplacée par la valeur du premier argument
suivant le format. La seconde le sera par la valeur du second argument
suivant le format et ainsi de suite. Il faut vérifier qu'il y a assez
d'arguments pour toutes les séquences du format (il peut y en avoir trop).
Séquence | l'argument remplaçant la séquence doit être |
% c |
un caractère seul |
% s |
une chaîne de caractère |
% d |
un entier (affiché en décimal) |
% o |
un entier (affiché en octal) |
% x |
un entier (affiché en héxadécimal) |
% u |
un entier non signé (affiché en décimal) |
% f |
un réel (affiché normalement) |
% e |
un réel (affiché en notation exponentielle) |
% g |
un réel (au mieux entre f et e) |
On peut introduire entre le %
et le caractère de spécification
de format d'affichage quelques caractères de contrôles d'affichage :
-
permet d'afficher l'argument
aligné à gauche (par défaut à droite).
+
fait qu'un nombre est toujours
affiché avec son signe (par défaut seul le moins est affiché).
.
suivi d'un nombre permet de
spécifier pour les valeurs réels le nombre de chiffres après
la virgule.
Exemples :
double a=3.141592653589793115997963;
printf("Pi = %e n", a);
printf("Pi = %f n", a);
printf("Pi = %15f n", a);
printf("Pi = %18.13f n", a);
printf("Pi = %+.13f n", a);
printf("Pi = %-+18.13f n", a);
printf("Pi = %.25f n", a);
Affiche :
Pi = 3.141593e+00 Pi = 3.141593 Pi = 3.141593 Pi = 3.1415926535898 Pi = +3.1415926535898 Pi = +3.1415926535898 Pi = 3.1415926535897931159979635Il faut inclure le fichier d'en-tête standard
stdio.h
avant de pouvoir utiliser la fonction printf
:
#include <stdio.h>
Nous ne détaillerons pas complètement la fonction scanf
dont le fonctionnement n'est pas réellement évident. Nous ne
donnerons que quelques exemples.
scanf
permet de lire et d'interpréter du texte saisie
par l'utilisateur au clavier. Comme printf
, cette
fonction utilise un format suivi d'un nombre variable
d'arguments que scanf
devra lire. Comme ces arguments
vont être modifiés par la fonction, il faut toujours lui
envoyer des pointeurs sur les variables à lire.
Dans le format, c'est encore le caractère %
qui
spécifie l'utilisation des arguments. Nous donnons dans le tableau
9.2 la liste des principales séquences utilisables.
Séquence | interprétation de la saisie | type de l'argument |
% c |
un caractère seul | char * |
% s |
une chaîne de caractère | char * |
% d |
un entier en décimal | int * |
% o |
un entier en octal (précédé d'un 0) | int * |
% x |
un entier en héxa (précédé de 0x) | int * |
% u |
un entier non signé décimal | unsigned int * |
% f |
un réel | float * |
% e |
un réel | float * |
% g |
un réel | float * |
Attention : il faut faire précéder les caractères
spécifiant un entier (d, o, x, u) du caractère l
pour
spécifier que l'entier est de type long *
ou du
caractère h
pour spécifier que l'entier est de type
short *
. De même pour les réels, si le caractère est
précédé d'un l
alors le type est double *
.
Exemples :
double a;
int g;
char str[300];
printf("Donnez la valeur de a :");
scanf("%lf", &a);
printf("Donnez la valeur de g (en octal) :");
scanf("%o", &g);
printf("Donnez la valeur de str :");
scanf("%s", str);
Remarque : dans le cas d'un tableau de caractères, il
ne faut pas mettre de &
devant le nom du tableau puisque
ce nom représente déjà un pointeur sur le tableau.
Il faut inclure le fichier d'en-tête standard stdio.h
avant de pouvoir utiliser la fonction scanf
:
#include <stdio.h>
La fonction malloc
permet de demander au système de
réserver un espace mémoire afin de l'utiliser dans un
programme C. L'allocation de la mémoire se fait de manière
dynamique.
Pour pouvoir utiliser la fonction malloc
, il faut
inclure le fichier d'en-tête standard stdlib.h
:
#include <stdlib.h>
Le seul paramètre de malloc
est la taille en nombre
d'octets du bloc mémoire à allouer. Le résultat de
malloc
est de type void *
(c'est à dire un
pointeur générique). Il faut le convertir en un pointeur sur
le type de données que l'on veut stocker.
Pour connaître la taille d'un type, on utilise l'opérateur
sizeof
. L'utilisation de sizeof
permet de
garantir que le programme se compilera correctement quelque
soit la machine utilisée (ne pas oublier qu'un double
n'occupe pas obligatoirement la même place sur toutes les
machines).
Dans l'exemple suivant, on alloue dynamiquement tout d'abord un int
,
puis un complexe
et enfin un tableau de 100 short
:
int * pInt;
complexe * pComplexe;
short * pShortTab;
pInt = (int *) malloc(sizeof(int));
pComplexe = (complexe *) malloc(sizeof(complexe));
pShortTab = (short *) malloc(sizeof(short) * 100);
Une fois ces allocations dynamiques effectuées, il est possible de stocker des données dans l'espace mémoire pointé par ces trois pointeurs comme avec n'importe quel autre pointeur.
La fonction malloc
retourne la valeur NULL
si il
n'y a plus assez de place pour allouer un bloc de la taille
demandée. Dans un programme C correct, on doit donc tester la
valeur de retour de malloc
pour vérifier que
l'allocation s'est bien déroulée. En général, s'il n'y a plus
assez de mémoire, on arrête le programme grâce à l'instruction
exit
qui stoppe instantanément le programme :
int * pTabInt;
pTabInt = (int *) malloc(sizeof(int) * 10000);
if (pTabInt == NULL) {
printf("Plus assez de mémoire pour continuer !\
n");
exit(1);
}
Ceci étant, si un pointeur contient la valeur NULL
, il
est obligatoirement invalide et toute tentative d'accéder à
son contenu provoquera une erreur.
Toute la mémoire allouée dynamiquement durant l'exécution d'un
programme sera libéré à la fin du programme. Mais, il est plus
propre et surtout moins consommateur de ressources mémoire de
libérer l'espace mémoire que l'on a réservé dès qu'on n'en a
plus besoin. La fonction free
permet de libérer un bloc
mémoire précédemment alloué via malloc
. Cette espace
mémoire est rendu au système qui pourra le réutiliser pour un
autre usage (par exemple un autre malloc
).
Le seul paramètre de free
est un pointeur (ce pointeur
doit normalement être de type void *
. Néanmoins, le
compilateur effectue tout seul la conversion si c'est un
pointeur d'un autre type). Ce pointeur doit absolument
pointé sur un espace mémoire alloué par malloc
.
Pour pouvoir utiliser la fonction free
, il faut
inclure le fichier d'en-tête standard stdlib.h
:
#include <stdlib.h>
En général, après la libération de l'espace mémoire qu'il
pointait, on stocke la valeur NULL
dans le pointeur
afin d'éviter un accès involontaire à l'espace mémoire
libéré. De même, tant qu'un pointeur ne pointe vers rien de
spécial, on l'initialise avec la valeur NULL
:
int * pTabInt = NULL;
/* le contenu de pTabInt n'est pas accessible */
...
pTabInt = (int *) malloc(sizeof(int) * 10);
/* on peut utilises les dix elements du tableau pointés
par pTabInt : pTabInt[0], ..., pTabInt[9] */
...
free(pTabInt);
pTabInt = NULL;
/* le contenu du pointeur pTabInt n'est plus utilisable */
...