Exercice langage C: Position d'une chaîne de caractère dans un Fichier

Écrire une fonction qui retourne les différentes positions d'une chaîne de caractères dans un fichier texte ou binaire.

Le nom du fichier, ainsi que la chaîne seront transmis en argument au programme.

On pourra le tester avec les arguments suivants :

  1. exo18 exo18_data_bin save
  2. exo18 exo18_data_bin SAVE
  3. exo18 exo18_data_txt où-suis-je?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include 
#include 
#include 
#include 
#include 
#include 

int    *positions;
int     nb_positions;
size_t  taille_bloc;

§MEVBCBfstatic void init( size_t longueur )
{
  positions = NULL;
  nb_positions = 0;
  taille_bloc = BUFSIZ - longueur + 1;

  return;
}

§MEVBCBfint main( int argc, char **argv )
{
   void  usage(char *s);
   void  strrech( char *buffer, int nblus,
                  char *ChaineAchercher, size_t longueur );
   int     fd;
   char    buffer[BUFSIZ];
   char   *ChaineAchercher;
   size_t  longueur;
   int     nblus;

   /*
    * Le fichier et la chaîne à chercher
    * ont-ils été passés en argument ?
    */

   if ( argc != 3 )
     usage( argv[0] );
   ChaineAchercher = argv[2];
   longueur = strlen( ChaineAchercher );

   /*
    * initialisation des variables globales.
    */
   init( longueur );

   /* Ouverture du fichier passé en argument. */

   if( (fd = open( argv[1], O_RDONLY )) == -1 )
   {
      perror( "open" );
      exit( 1 );
   }

    /* Boucle de lecture du fichier. */

   while( nblus = read( fd, buffer, sizeof buffer ) )
   {
     /*
      * Récupération des positions de la chaîne
      * dans le buffer courant.
      */

     strrech( buffer, nblus, ChaineAchercher, longueur );

     /*
      * Si BUFSIZ caractères ont été lus, on
      * recule de (longueur-1) caractères
      * dans le fichier, pour être sûr de n'oublier
      * aucune position de la chaîne.
      */

     if( nblus == BUFSIZ )
       lseek( fd, -(long)(longueur - 1), SEEK_CUR );
   }
   close( fd );

   /* Impression des positions trouvées. */

   if ( nb_positions == 0 )
     printf( "La chaîne \"%s\" n'a pas été trouvée\n"
             "dans le fichier \"%s\".\n",
              ChaineAchercher, argv[1] );

    else
   {
     int pos;

     printf( "Dans le fichier \"%s\", la chaîne \"%s\"\n"
             "a été trouvée aux positions :\n\n",
              argv[1], ChaineAchercher );
     for( pos=0; pos
/*
 * Fonction de récupération des positions
 * de la chaîne dans le buffer courant.
 */

§MEVBCBfvoid strrech( char *s, int nblus,
              §MEVBCBfchar *ChaineAchercher, size_t longueur )
{
   char       *buffer, *ptr;
   static int  n = 0, nombre_octets_lus = 0;
   int         i;

   /*
    * On prend garde de remplacer les éventuels caractères
    * "nuls" par des blancs pour pouvoir utiliser
    * la fonction "strstr".
    */

   buffer = malloc( nblus+1 );
   memcpy( buffer, s, nblus );
   for( i=0; i
   /* Boucle de recherche de la chaîne. */

   for( ptr=buffer;
        ptr=strstr( ptr, ChaineAchercher );
        ptr+=longueur )
   {
     /*
      * extension du vecteur positions.
      */

     positions = (int *)realloc( positions, ++n*sizeof(int) );
     assert( positions != NULL );

     /*
      * position de la chaîne trouvée par
      * rapport au début du bloc lu.
      */

     positions[n-1] = ptr - buffer + 1;

     /*
      * position de la chaîne trouvée par
      * rapport au début du fichier.
      */

     positions[n-1] += nombre_octets_lus;
   }
   free( buffer );

    /*
    * Nombre d'octets déjà lus dans le fichier.
    */

   nombre_octets_lus += taille_bloc;
   nb_positions = n;

   return;
}

§MEVBCBfvoid usage(char *s)
{
   fprintf( stderr, "usage: %s fichier"
                    " ChaineAchercher.\n", s );
   exit(1);
}