mardi 13 décembre 2011

Lire une ligne longue avec fgets

La fonction fgets de la bibliothèque standard du langage C permet de lire une chaine de caractère de longueur limitée dans un flux.
Vous allez compléter une fonction lire_ligne répondant au spécifications suivantes :


  • Retour d'une ligne lue dans un flux texte passé en paramètre.
  • Vous éliminerez les caractères de saut de ligne lus.
  • La longueur des lignes lues n'est pas limitée.
  • Contrôle des paramètres et retour des codes d'erreurs systèmes, détection de la fin du fichier.
  • Vous utiliserez au maximum les fonctions de la bibliothèque standard du langage C : allocation mémoire, chaines de caractères...
  • Son prototype est donné par lire_ligne.h.
  • Vous utiliserez le programme de main_lire_ligne.c pour lire_ligne.
  • Vous devrez traiter le fichier test_lire_ligne.txt fourni.
Solution
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include "lire_ligne.h"
 
/*@null@*/ char *lire_ligne(size_t tailleBufferLecture,
        FILE * restrict flux, int *pCodeRetour)
{
   // Declarations
   char *chaineRetour = NULL;
   bool litEncore = true;
   bool rienLu = true;
   int codeRetour = EXIT_SUCCESS;
 
   // Controle rapide des parametres.
   // Si quelque chose ne va pas, arret.
   assert(tailleBufferLecture > 0);
   assert(flux != NULL);
 
   // On reinitialise errno
   errno = 0;
 
   // Boucle de lecture d'une ligne eventuellement longue
   do
   {
      size_t positionEcriture;
      char *nouvelleChaine;
      litEncore = false;
 
      // Demande d'une nouvelle zone memoire
      positionEcriture =
         (chaineRetour == NULL) ? 0 : strlen(chaineRetour);
      nouvelleChaine = realloc(chaineRetour,
         positionEcriture + tailleBufferLecture);
      if (nouvelleChaine == NULL) // Si probleme d'allocation
      {
         codeRetour = errno;
         free(chaineRetour);
         chaineRetour = NULL;
      }
      else // Si le systeme a accorde la memoire
      {
         chaineRetour = nouvelleChaine;
          if (fgets(chaineRetour+positionEcriture,
            (int)tailleBufferLecture, flux)
            != NULL)
         {
            // Recherche si un \n a ete lu en fin de chaine.
            char *positionNewLine = strrchr(chaineRetour, '\n');
            rienLu = false;
            if (positionNewLine != NULL)
            {
               // Suppression du caractere de fin de ligne \n,
               *positionNewLine = '\0';
            }
            else // fgets n'a pas pu lire la ligne complete.
            {
               litEncore = true;
            }
         } else if (ferror(flux) != 0)
         {
            codeRetour = errno;
            free(chaineRetour);
            chaineRetour = NULL;
         } else if (feof(flux) != 0)
         {
            codeRetour = EOF;
            if (rienLu)
            {
               free(chaineRetour);
               chaineRetour = NULL;
            }
         }
      }  // else if (nouvelleChaine == NULL)
   } while (litEncore);
 
   // Retour des resultats. 
   *pCodeRetour = codeRetour;
   return chaineRetour;
} 

Aucun commentaire:

Enregistrer un commentaire