next up previous contents 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':

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 up previous contents Next:  #include et les prototypes. Up: Les bases du C. Previous:  Lire des arguments en   Table des matières  
1-01-2006