Fonction de lecture dans un fichier, et problème avec strchr
J'ai écrit cette fonction, tout est décrit dans le code:
Code:
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
|
char* LireLigneFichier(char *lecture, int taille, FILE *pf)
/* Cette fonction place dans "lecture" une chaîne de "taille" caractères,
à partir d'une ligne du fichier "pf".
Si la longueur de la ligne est supérieure à "taille", seulement les "tailles"
premiers caractères de la ligne sont placé dans "lecture", et le reste
de la ligne est ignoré.
En revanche la lecture suivante sera effectuée sur la ligne suivante,
on pourra ainsi lire cette nouvelle ligne sans problème due au reste
de la ligne précédente.
Retourne NULL si rien n'a été lu. */
{
char *temp=NULL;
char *res;
char buffer[1024]; /* "buffer" est utilisée pour lire une ligne entière
du fichier.
Cette fonction peu lire au maximum des lignes de
"1024-'\n'-1" caractères. */
res=fgets(buffer, sizeof(buffer), pf); /* place la ligne lu dans
buffer ('\n' inclut), d'une taille
de sizeof(buffer)-1 carac.
retourne NULL si rien n'a été lu */
/* exemple de lecture: "abc\n\0" */
temp=strchr(buffer, '\n'); /* recherche la ou se trouve le '\n' */
if(temp!=NULL)
*temp='\0'; /* écrasement du '\n'.
exemple: "abc\n\0" devient "abc\0\0" */
/* note: sous linux(gcc) il faut mettre *(temp-1)='\0'
sous dev-c++(gcc) *temp='\0' */
strncpy(lecture, buffer, taille);
lecture[taille-1]='\0'; /* car si la taille de "buffer" est >= à "taille",
alors il n'y aura pas de '\0' terminal dans
"lecture".
Donc on écrase le dernier caractére avec '\0' */
return res;
} |
Je voudrais déjà avoir votre avis sur cette fonction, et aussi sur le problème de la différence de comportement entre linux et windows (j'y fait référence dans les commentaires), je pense que le problème se situe au niveau du strchr...
Re: Fonction de lecture dans un fichier, et problème avec st
Citation:
Envoyé par neird
J'ai écrit cette fonction, tout est décrit dans le code:
<...>
Je voudrais déjà avoir votre avis sur cette fonction, et aussi sur le problème de la différence de comportement entre linux et windows (j'y fait référence dans les commentaires), je pense que le problème se situe au niveau du strchr...
A la lumière des reflexions d'Anomaly, j'en déduis que la différence de comportement vient de ce que le fichier est probablement ouvert en mode binaire ("rb") alors qu'il devrait l'être en mode texte ("r")..
Dans ce cas, ce code (pas besoin de chaine intermédiaire) ...
Code:
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
|
#include <stdio.h>
#include <string.h>
char* LireLigneFichier (char *lecture, int taille, FILE *pf)
{
char *res = fgets (lecture, taille, pf);
if (res != NULL)
{
char *p = strchr (buffer, '\n');
if (p != NULL)
{
*p = 0;
}
else
{
/* prendre les mesures qui s'imposent
* (tronquer, lire la suite etc.)
*/
}
}
return res;
} |
... est portable à condition que le fichier lu ait été créé par le même système. En effet, le format des fichiers textes diffère d'un système à l'autre :
(sauf erreur ou omission de ma part) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
:----------------:--------------:----------------:
: Système : Fin de ligne : Fin de fichier :
:----------------:--------------:----------------:
: Unix : : :
: Mac X : 0x0A LF : Sans objet :
: Linux : : :
:----------------:--------------:----------------:
: Mac (non unix) : Ox0D CR : Sans objet :
:----------------:--------------:----------------:
: MS-DOS : Ox0D 0x0A : 0x1A :
: Windows : CR LF : ^Z :
: Windows NT : : :
:----------------:--------------:----------------:
: VMS STREAM_CR : Ox0D CR : Sans objet :
:----------------:--------------:----------------:
: VMS STREAM_LF : 0x0A LF : Sans objet :
:----------------:--------------:----------------:
: VMS STREAM_CRLF: Ox0D 0x0A : Sans objet :
:----------------:--------------:----------------: |
Mais si on doit lire sur une machine Linux un fichier texte créé par une machine MS-DOS ou Mac, ou inversement, le comportement est indéfini. Détails dans le post d'Anomaly.
Re: Fonction de lecture dans un fichier, et problème avec st
Merci à vous, j'ai bien compris le problème des fins de lignes.
Et effectivement, ce sont les fichiers générés sous windows qui se révélent illisible avec cette fonction sous linux.
Maintenant je voudrais revenir sur cette fonction proposé:
Citation:
Envoyé par Emmanuel Delahaye
Dans ce cas, ce code (pas besoin de chaine intermédiaire) ...
Code:
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
|
#include <stdio.h>
#include <string.h>
char* LireLigneFichier (char *lecture, int taille, FILE *pf)
{
char *res = fgets (lecture, taille, pf);
if (res != NULL)
{
char *p = strchr (buffer, '\n');
if (p != NULL)
{
*p = 0;
}
else
{
/* prendre les mesures qui s'imposent
* (tronquer, lire la suite etc.)
*/
}
}
return res;
} |
Le problème est que si par exemple je lis une chaine de 10 carac (LireLigneFichier(c, 10, f)), si par n'importe quel hasard, la ligne que je lis fait plus de 10 caractères, alors à la lecture suivante(des 10carac suivants), je lirais la fin de la ligne. Or je préferes passer à la ligne suivante et ignorer la fin de la ligne précédente. C'est pour cela que j'utilise une variable intermédiaire buffer, ainsi je suis "sur" de lire entièrement la ligne.
Je sais pas si c'est très clair...
Re: Fonction de lecture dans un fichier, et problème avec st
Citation:
Envoyé par neird
Merci à vous, j'ai bien compris le problème des fins de lignes.
Et effectivement, ce sont les fichiers générés sous windows qui se révélent illisible avec cette fonction sous linux.
Maintenant je voudrais revenir sur cette fonction proposé:
<...>
Le problème est que si par exemple je lis une chaine de 10 carac (LireLigneFichier(c, 10, f)), si par n'importe quel hasard, la ligne que je lis
Ce n'est pas du 'hasard'. Il est tout à fait possible que la ligne à lire fasse plus de 10 caractères. Le cas est prévu dans le 'else'. Simplement, je te laisse faire le traitement que tu veux. Pour tronquer, il suffit de lire tous les caractères jusqu'au prochain '\n' ou EOF.
Code:
1 2 3 4 5 6 7 8 9
|
else
{
/* ignorer la suite de la ligne */
int c;
while ((c = fgetc(pf)) != '\n' && c != EOF)
{
}
} |
Citation:
fait plus de 10 caractères, alors à la lecture suivante(des 10carac suivants), je lirais la fin de la ligne. Or je préferes passer à la ligne suivante et ignorer la fin de la ligne précédente. C'est pour cela que j'utilise une variable intermédiaire buffer, ainsi je suis "sur" de lire entièrement la ligne.
Je sais pas si c'est très clair...
Moyennement, en tout cas, je le confirme, la chaine intermédiaire est inutile.