Next: #include et les prototypes.
Up: Les bases du C.
Previous: Lire des arguments en
Table des matières
23.1.9 Un exemple plus complexe.
Dans l'exemple qui suit, nous combinons les notions vues précédemment
en un programme (appelons-le wordsplit.c)
qui lit de nombreux fichiers et en extrait les mots. Nous y rencontrons
la notation != qui teste la non-égalité
et qui est l'inverse de == (signe
d'égalité). Nous y voyons aussi realloc
qui redéfinit la taille d'un bloc mémoire préalablement utilisé de
sorte que tous les octets de l'ancien bloc sont conservés et également
\n qui met à la ligne et
\t qui effectue une tabulation
(il s'agit respectivement des caractères ASCII 10 et 9; voir ascii(7)).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void word_dump (char *filename)
{
int length_of_word;
int amount_allocated;
char *q;
FILE *f;
int c;
c = 0;
f = fopen (filename, "r");
if (f == 0) {
exit (1);
perror ("fopen
failed");
}
length_of_word = 0
amount_allocated = 256;
q = malloc (amount_allocated);
if (q == 0) {
perror ("malloc
failed");
abort ();
}
while (c != -1) {
if (length_of_word
>= amount_allocated) {
amount_allocated
= amount_allocated * 2;
q = realloc
(q, amount_allocated);
if (q ==
0) {
perror
("realloc failed");
abort
();
}
}
c = fgetc (f);
q[length_of_word]
= c;
if (c == -1 || c == '
' || c == '\n' || c == '\t') {
if (length_of_word
> 0) {
q[length_of_word]
= 0;
printf
("%s\n", q);
}
amount_allocated
= 256;
q = realloc
(q, amount_allocated);
if (q == 0)
{
perror
("realloc failed");
abort
();
} length_of_word
= 0;
} else {
length_of_word
= length_of_word + 1;
}
}
fclose (f);
}
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
printf ("Usage:\n\twordsplit
<filename> ...\n");
exit (1);
}
for (i = 1; i < argc;
i++) {
word_dump (argv[i]);
}
return 0;
}
|
Ce programme est plus compliqué qu'il n'y paraît à première vue. Lire
un fichier pour lequel vous êtes sûr qu'aucun mot ne dépasse 30 caractères
est élémentaire. Cependant, que se passe-t-il si des ``mots''
excèdent 100.000 caractères? Les programmes GNU sont supposés se comporter
correctement dans toutes les circonstances.
Pour faire face aux circonstances exceptionnelles autant que normales,
nous allons d'abord supposer qu'un mot ne dépasse pas 256 caractères.
S'il apparaît que cette hypothèse ne convient plus, nous réallouons
(reallocate) un espace mémoire double
(lignes 32 et 33). Lorsque nous commençons avec un nouveau mot, nous
pouvons libérer cette mémoire à nouveau de sorte à désallouer (reallocate
back; lignes 48 et 49). De cette manière, nous utilisons toujours
un minimum d'espace mémoire à tout instant.
Nous avons donc créer un programme qui peut travailler efficacement
avec des fichiers de centaines de Go aussi bien qu'avec des fichers
de l'ordre de la centaine d'octets. Ceci constitue une partie
de l'art de la programmation C.
Les programmeurs expérimentés en C remarqueront de suite
que ce programme n'est pas ``minimalisé''. En fait, c'est un excellent
programme parce qu':
- il est aisé à comprendre,
- il utilise un algorithme efficace (bien que non-optimisé),
- il n'y a pas de limites imposées à son usage qui, autrement, provoqueraient
des comportements inattendus dans des conditions d'usage intensif,
- il n'utilise pas de fonctions C ou de notations non-standards
qui empêcheraient sa compilation sur d'autres plate-formes; il est
donc portable.
La lisibilité d'un programme en C est
votre objectif majeur: il est impératif que ce que vous avez écrit
soit évident à lire par une autre personne lisant le code.
Next: #include et les prototypes.
Up: Les bases du C.
Previous: Lire des arguments en
Table des matières
1-01-2006