Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème avec une fin de fichier

11 réponses
Avatar
Michel
Bonjour,

Je dois écrire une fonction chargée d'extraire le 2ème champs de chacune
des lignes d'un fichier texte (exemple de lignes reproduit en bas de post).
Ce champ est composé de 7 caractères (exemple : 945BB04) et je ne dois
stocker que les champs commençants par '9'. Bien sûr, avant de stocker
un champs, la fonction vérifie s'il n'a pas déjà été préalablement
stocké (champs identiques).

Mais je rencontre un problème en fonction de la fin du fichier qui peut
être n'importe quoi, c'est à dire que la dernière ligne du fichier peut
se terminer par n'importe quoi, exemples :
- par une série d'espaces SANS '\n' : le pgm fonctionne bien.
- par un '\n' (avec ou sans espace avant, peu importe) : le pgm
fonctionne bien.
- mais si la dernière ligne est composée uniquement d'espaces suivi OU
NON par un '\n' ou bien s'il y a plusieurs lignes d'espaces avec ou sans
'\n' à la fin : le pgm boucle indéfiniment.
Et c'est ce dernier cas qui pose un problème : le programme boucle
indéfiniment sur cette fin de fichier (lignes de code commentées en
majuscules)
Comment procéder pour que le programme fonctionne quelque soit la
dernière ligne?
Merci d'avance.
Michel


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "entete.h"
#include "definition.h"
#define NOM_MODULE "TraiterFichierRF.c"
#define TAILLE_BUFFER 8

void TraiterFichierRF(FILE *pFichierRF) {

int caractereLu;
char **pTabIdPub = NULL;
char identifiantLu[TAILLE_BUFFER];
Booleen idNonStocke; /*typedef enum logique {FAUX, VRAI} Booleen; dans
un .h*/

int i;
int j = 0;
int k;


/* tant que l'on n'a pas atteint la fin de fichier */
while((caractereLu = fgetc(pFichierRF)) != EOF) {
i = 0;
idNonStocke = FAUX;

/* tant que l'on n'a pas trouvé un 9 */
while(caractereLu != '9')
caractereLu = fgetc(pFichierRF);

/* on mémorise le 9 */
identifiantLu[i++] = caractereLu;

/* on lit et mémorise jusqu'à l'espace suivant exclu, sans
toutefois dépasser 6 caractères */
while((caractereLu = fgetc(pFichierRF)) != ' ' && i < 7)
identifiantLu[i++] = caractereLu;

/* on ajoute le caractère de fin de chaine */
identifiantLu[i] = '\0';

/* on vérifie si le contenu de identifiantLu est déjà stocké */
if(j >= 1) {
for(k = 0; k < j; k++) {
if(strcmp(pTabIdPub[k], identifiantLu))
idNonStocke = VRAI;
}
}

if(j <= 1 || idNonStocke == VRAI) {
/* on réserve de la mémoire pour stocker un pointeur vers la chaine
id_de_la_pub */
if((pTabIdPub = realloc(pTabIdPub, sizeof(char*) *(j+1))) ==
NULL) {
printf("Module \"%s\"\nLigne %d : echec d'allocation memoire
par \"realloc\".\n"
"Le programme ne peut continuer.\n\n",
NOM_MODULE, __LINE__);
printf("Pressez <enter> pour quitter le programme.");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

/* on stocke l'identifiant de la pub */
if((pTabIdPub[j] = strdup(identifiantLu)) == NULL) {
printf("Module \"%s\"\nLigne %d : echec d'allocation memoire
par \"strdup\".\n"
"Le programme ne peut continuer.\n\n", NOM_MODULE,
__LINE__);
printf("Pressez <enter> pour quitter le programme.");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}
}

j++;

/* on lit jusqu'à la ligne suivante : ICI LE PGM BOUCLE EN
FONCTION DU TYPE DE LA DERNIERE LIGNE */
while((caractereLu = fgetc(pFichierRF)) != '\n' /*|| caractereLu
!= EOF*/) {
if(caractereLu == EOF)
break;
}
}

/* affichage des lignes stockées */
for(k = 0; k < j; k++) {
printf("Ligne n. %05d : %s\n", k + 1, pTabIdPub[k]);
}
}

Exemple de lignes contenues dans le fichier :

SINGLE 945BB04 PUB ABALONE
00:00:20.15 09:59:59.17 12/01/2003 0
12/01/2003 00:00:00 12/31/2003
KJH
Beta Stereo
SINGLE 942BB27 PUB AIRWICK
00:00:15.15 09:59:59.17 11/02/2003 0
11/02/2003 00:00:00 12/02/2003
AA
Beta Stereo
SINGLE 937BB30 PUB AIRWICK
00:00:20.15 09:59:59.17 09/22/2003 0
09/22/2003 00:00:00 10/22/2003
UYI
Beta Stereo
SINGLE 947BB15 PUB AMBIPUR
00:00:20.15 09:59:59.17 11/22/2003 0
11/22/2003 00:00:00 12/22/2003
GFV
Beta Stereo
SINGLE 941BB09 PUB ANDROS
00:00:15.16 09:59:59.17 10/09/2003 0
10/09/2003 00:00:00 11/08/2003
FG
Beta Stereo
SINGLE 941BB07 PUB ANDROS
00:00:15.16 09:59:59.17 10/09/2003 0
10/09/2003 00:00:00 11/08/2003
FG
Beta Stereo

10 réponses

1 2
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Michel <pas_de_spam> wrote:

Mais je rencontre un problème en fonction de la fin du fichier qui peut
être n'importe quoi, c'est à dire que la dernière ligne du fichier peut
se terminer par n'importe quoi, exemples :
- par une série d'espaces SANS 'n' : le pgm fonctionne bien.
- par un 'n' (avec ou sans espace avant, peu importe) : le pgm
fonctionne bien.
- mais si la dernière ligne est composée uniquement d'espaces suivi OU
NON par un 'n' ou bien s'il y a plusieurs lignes d'espaces avec ou sans
'n' à la fin : le pgm boucle indéfiniment.
Et c'est ce dernier cas qui pose un problème : le programme boucle
indéfiniment sur cette fin de fichier (lignes de code commentées en
majuscules)
Comment procéder pour que le programme fonctionne quelque soit la
dernière ligne?


Il y a plusieurs fonctions de lecture dans ton code. Chacune peut tomber sur
un EOF. Le test doit êtr fait à chaque fois.

AMA, il serait beucoup plus simple de traiter ligne par ligne avec fgets(),
et de chercher '9' avec strstr()...

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Michel

AMA, il serait beucoup plus simple de traiter ligne par ligne avec fgets(),
et de chercher '9' avec strstr()...


strchr plutôt, car je dois rechercher un char (qui sera le début d'une
chaine, certe)?

Effectivement, j'avais pensé lire ligne après ligne par fgets mais comme
elles sont relativement longues et que je n'ai besoin d'extraire que
des infos situées en - presque - début de ligne, je n'avais pas voulu
consommer de la mémoire inutilement.
Depuis, je me suis ravisé et je poste mon nouveau code qui fonctionne
dans tous les cas cette fois-ci.
Peut-être que quelqu'un y décèlera des bug 'cachés', notamment avec les
pointeurs qui sont très utilisés.
Merci d'avance.
Michel


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "entete.h"
#include "definition.h"

#define NOM_MODULE "TraiterFichier.c"


InfosFichier * TraiterFichier(FILE *pFichierSource) {

static InfosFichier InfosFichier_t;
InfosFichier *pInfosFichier_t = &InfosFichier_t;
char ligneLue[TAILLE_LIGNE];
char *pCaractereTrouve;
char identifiantLu[TAILLE_BUFFER];
char **pTabIdPub = NULL;
Booleen idNonStocke;
int i, j = 0, k, l;

/* lecture des lignes */
while(fgets(ligneLue, TAILLE_LIGNE, pFichierSource) != NULL) {
i = 0;
l = 0;
pCaractereTrouve = NULL;
idNonStocke = FAUX;

/* on recherche le premier '9' de la ligne */
if((pCaractereTrouve = strchr(ligneLue, '9')) == NULL)
break;

else {
/* on le mémorise */
identifiantLu[i++] = *pCaractereTrouve++;

/* on mémorise les 6 caractères suivants */
while(*pCaractereTrouve != ' ' && l++ < 6)
identifiantLu[i++] = *pCaractereTrouve++;
}

/* on ajoute le caractère de fin de chaîne */
identifiantLu[i] = '';

/* on vérifie si le contenu de identifiantLu est déjà stocké */
if(j >= 1) {
for(k = 0; k < j; k++) {
if(strcmp(pTabIdPub[k], identifiantLu))
idNonStocke = VRAI;
}
}

if(j <= 1 || idNonStocke == VRAI) {
/* on réserve de la mémoire pour un pointeur vers char */
if((pTabIdPub = realloc(pTabIdPub, sizeof(char*) * (j+1))) = NULL) {
printf("n");
printf("Module "%s"nLigne %d : echec d'allocation memoire
par "realloc".n"
"Le programme ne peut continuer.nn",
NOM_MODULE, __LINE__);
printf("Pressez <enter> pour quitter le programme.");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

/* on mémorise l'id trouvé */
if((pTabIdPub[j] = strdup(identifiantLu)) == NULL) {
printf("n");
printf("Module "%s"nLigne %d : echec d'allocation
memoire par "strdup".n"
"Le programme ne peut continuer.nn", NOM_MODULE,
__LINE__);
printf("Pressez <enter> pour quitter le programme.");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}
}
j++;
}

/* on trie le tableau de données : à faire */
//qsort(


/* affichage des lignes stockées */
for(k = 0; k < j; k++)
printf("Ligne n. %04d : %sn", k + 1, pTabIdPub[k]);


/* valorisation des champs de la structure */
InfosFichier_t.pTabIdPub = pTabIdPub;
InfosFichier_t.nbElement = j;

return pInfosFichier_t;
}

Avatar
Michel


/* on recherche le premier '9' de la ligne */
if((pCaractereTrouve = strchr(ligneLue, '9')) == NULL)
break;


oups, je viens de me rendre compte que ce break n'a absoluement rien a
faire là.
Une instruction vide devrait suffire.
Michel

Avatar
Bruno Desthuilliers
Michel wrote:

AMA, il serait beucoup plus simple de traiter ligne par ligne avec
fgets(), et de chercher '9' avec strstr()...



strchr plutôt, car je dois rechercher un char (qui sera le début d'une
chaine, certe)?

Effectivement, j'avais pensé lire ligne après ligne par fgets mais comme
elles sont relativement longues et que je n'ai besoin d'extraire que
des infos situées en - presque - début de ligne, je n'avais pas voulu
consommer de la mémoire inutilement.


"Premature optimisation is the root of all evil..."

Bruno


Avatar
Michel

"Premature optimisation is the root of all evil..."


Soit!
Michel, vive la RAM pas chère...

Avatar
Pascal
Bruno Desthuilliers wrote:
"Premature optimisation is the root of all evil..."


pour mon info, c'est une citation de qui?
--
Pascal

Avatar
Pascal
Pascal wrote:

Bruno Desthuilliers wrote:

"Premature optimisation is the root of all evil..."



pour mon info, c'est une citation de qui?


arf google m'a répondu! au fait s/optimisation/optimization
--
Pascal


Avatar
Bruno Desthuilliers
Pascal wrote:
Pascal wrote:

Bruno Desthuilliers wrote:

"Premature optimisation is the root of all evil..."


pour mon info, c'est une citation de qui?



arf google m'a répondu! au fait s/optimisation/optimization


<PAQJS>
... les deux orthographes sont acceptables, la seconde ('z') étant plus
spécialement US
</PAQJS>



Avatar
Gabriel Dos Reis
Pascal writes:

| Pascal wrote:
|
| > Bruno Desthuilliers wrote:
| >
| >> "Premature optimisation is the root of all evil..."
| > pour mon info, c'est une citation de qui?
|
| arf google m'a répondu! au fait s/optimisation/optimization

optimisation est british et optimisation est american.

-- Gaby
Avatar
Marc Lasson
Michel wrote:

/* on recherche le premier '9' de la ligne */
if((pCaractereTrouve = strchr(ligneLue, '9')) == NULL)
break;



oups, je viens de me rendre compte que ce break n'a absoluement rien a
faire là.
Une instruction vide devrait suffire.


Moué, c'est un peu capilotracté:
if (A) {/* rien */} else {quelquechose();}

C'est un peu equivalent à :

if (!A) {quelquechose();}

--
Marc.


1 2