débutant avec fgetc, fscanf, fprintf
Le
bpascal123
Hello cyberspace,
Je dois écrire un code qui lit un fichier et recopie le contenu
(enregistrement par enregistrement) dans un autre fichier. Je suis
arrivé à copier sur l'autre fichier sans trop de mal. Au départ, j'ai
fait appel à feof avec while ( !feof(P_SOURCE) != EOF ) fscanf fichier
sourcefprintf fichier destination . Je me suis rendu compte de
cette manière qu'à chaque fois, dans le fichier destination, il y
avait un un "ÿ" en fin fichier en dernière ligne. Je me demande si
quelqu'un n'a pas déjà rencontré l'affichage de ce caratère (ÿ) ?=
Est-
ce que c'est une représentation de EOF ?
Bref, j'ai pu résoudre cette situation avec while ( (c =
fgetc(P_SOURCE)) != EOF ) Au niveau de l'écriture du fichier tout
se déroule normalement et le résultat est ce que j'attends que ça soi=
t
enregistrement par enregistrement ou caractère par caractère
Maintenant je souhaite afficher à l'écran (dans le terminal) le
fichier destinatation et alors tout ce qui chaîne de caractère
s'affiche comme prévu mais les %d ne s'affichent pas comme prévu.
Voici les fonctions que j'utilise :
void ReadAndCopyRec( FILE *FP_SOURCE, FILE *FP_DESTI, int FTicket,
char FName[], char FPren[] )
{
while ( !feof(FP_SOURCE) )
{
fscanf(FP_SOURCE, "%d%s%s", &FTicket, FName, FPren) ;
fprintf(FP_DESTI, "%d%s%s", FTicket, FName, FPren) ;
}
}
void DisplayRec( FILE *FP_DESTI, int FTicket, char FName[], char
FPren[],
int nmax)
{
int c ;
while ( (c = fgetc(FP_DESTI)) != EOF )
{
fscanf(FP_DESTI, "%d%s%s", &FTicket, FName, FPren) ;
printf("%d%s%s", FTicket, FName, FPren) ;
}
}
Faire appel à ces 2 fonctions fonctionne bien pour ce qui est de la
copie dans le fichier destination, par contre l'affichage à l'écran
avec DisplayRec n'est pas celui de la copie ni du source pour %d,
FTicket. Le numéro de FTicket devien 0 à l'affichage écran alors qu'i=
l
est bien celui du fichier source dans le fichier destination.
Avec int FTicket[] dans les fonctions et (FTicket+i) dans fscanf et
FTicket[i] pour printf (int i = 0 et i++ dans while) pour une
lecture par adresse, le résultat est différent sans être meilleur.
Une idée?
Merci,
Pascal
Je dois écrire un code qui lit un fichier et recopie le contenu
(enregistrement par enregistrement) dans un autre fichier. Je suis
arrivé à copier sur l'autre fichier sans trop de mal. Au départ, j'ai
fait appel à feof avec while ( !feof(P_SOURCE) != EOF ) fscanf fichier
sourcefprintf fichier destination . Je me suis rendu compte de
cette manière qu'à chaque fois, dans le fichier destination, il y
avait un un "ÿ" en fin fichier en dernière ligne. Je me demande si
quelqu'un n'a pas déjà rencontré l'affichage de ce caratère (ÿ) ?=
Est-
ce que c'est une représentation de EOF ?
Bref, j'ai pu résoudre cette situation avec while ( (c =
fgetc(P_SOURCE)) != EOF ) Au niveau de l'écriture du fichier tout
se déroule normalement et le résultat est ce que j'attends que ça soi=
t
enregistrement par enregistrement ou caractère par caractère
Maintenant je souhaite afficher à l'écran (dans le terminal) le
fichier destinatation et alors tout ce qui chaîne de caractère
s'affiche comme prévu mais les %d ne s'affichent pas comme prévu.
Voici les fonctions que j'utilise :
void ReadAndCopyRec( FILE *FP_SOURCE, FILE *FP_DESTI, int FTicket,
char FName[], char FPren[] )
{
while ( !feof(FP_SOURCE) )
{
fscanf(FP_SOURCE, "%d%s%s", &FTicket, FName, FPren) ;
fprintf(FP_DESTI, "%d%s%s", FTicket, FName, FPren) ;
}
}
void DisplayRec( FILE *FP_DESTI, int FTicket, char FName[], char
FPren[],
int nmax)
{
int c ;
while ( (c = fgetc(FP_DESTI)) != EOF )
{
fscanf(FP_DESTI, "%d%s%s", &FTicket, FName, FPren) ;
printf("%d%s%s", FTicket, FName, FPren) ;
}
}
Faire appel à ces 2 fonctions fonctionne bien pour ce qui est de la
copie dans le fichier destination, par contre l'affichage à l'écran
avec DisplayRec n'est pas celui de la copie ni du source pour %d,
FTicket. Le numéro de FTicket devien 0 à l'affichage écran alors qu'i=
l
est bien celui du fichier source dans le fichier destination.
Avec int FTicket[] dans les fonctions et (FTicket+i) dans fscanf et
FTicket[i] pour printf (int i = 0 et i++ dans while) pour une
lecture par adresse, le résultat est différent sans être meilleur.
Une idée?
Merci,
Pascal

Poser une question


La première chose à faire avant d'utiliser une fonction est de lire sa
doc et de la comprendre. Relit la doc de feof() et tu verras qu'elle
ne fait pas ce que tu crois.
Pour déterminer si on est arrivé en fin de fichier, on teste la valeur
retournée par la fonction de lecture. Il n'y a pas d'alternative.
Effectivement c'est une solution correcte. (test de la valeur
retournée par fgetc()). D'ailleurs, pour une copie simple, on peut
simplifier par :
while (fgetc(P_SOURCE) != EOF )
...
Encore une fois feof() ne fait pas ce que tu crois. ... Il faut tester
la valeur retournée par la fonction de lecture (ici, fscanf()). Et pas
de devinettes. LIRE LA DOC. D'autre part, les 'n' dans le formatage
de fscanf() ne font pas non plus ce que tu crois. Ça perturbe tout...
A retirer. Il ne faut pas programmer au hasard, mais se conformer
strictement à la doc...
...
...
Mais c'est une blague ! Remplacer feof par fgetc ... après c'est normal que
cela ne puisse fonctionner de la même façon, en tant que comptable cela
devrait te sauter aux yeux !
Avant d'arriver à l'arithmétique des pointeurs, il faudrait déjà comme le
dit "ed" réussir à comprendre la doc sur les fonctions les plus simples.
J'ai lu la doc, en tant que comptable, il semble que feof ait un
passif non négligeable... :) Je dis en tant que comptable car certains
pensent que la comptablité se fait avec un cahier, une règle de
préférence longue pour tracer des traits, un bic et une calculatrice
ou une bonne tête pour le calcul de tête ... je pense que ce n'est pas
le sujet de cette discussion
Bref, d'après la doc ou plutôt des recherches, feof peut afficher 2
fois le dernier enregistrement lu, la 2ème fois est dû au premier
appel de la fonction à l'intérieur de la boucle test qui renvoie faux
et crée un "doublon" par un second affichage du dernier enregistrement
qui ne devrait pas avoir lieu...
Voilà ce que j'ai fait et c'est très bizarre mais j'ai cru un moment
que cette solution me suffisait pour mon niveau mais en fait c'est
encore moins fonctionnel :
void ReadAndCopyRec(FILE *FP_SOURCE, FILE *FP_DESTI, int FTicket, char
FName[], char FPren[])
{
while (1)
{
fscanf(FP_SOURCE, "%d%s%s", &FTicket, FName, FPren) ;
if ( feof(FP_SOURCE) )
break ;
fprintf(FP_DESTI, "%dn%sn%sn", FTicket, FName, FPren) ;
}
}
void DisplayRec(FILE *FP_DESTI, int FTicket, char FName[], char
FPren[] )
{
int i = 0 ;
while (1)
{
fscanf(FP_DESTI, "%d%s%s", &FTicket, FName, FPren) ;
if ( feof(FP_DESTI) )
break ;
printf("nTicket no. %d ", FTicket) ;
printf("nNom du titulaire : %s", FName ) ;
printf("nPrenom du titulaire : %s", FPren) ;
i++ ;
}
}
j'ai enlevé les n de la lecture de fscanf, c'est sûre qu'avec la
méthode de saisie plus haut, ça fonctionne. Mais ici avec feof à cett e
position, c'est juste un désordre, soit une boucle infinie, soit une
répétition de 100x puis stop à un chiffre nombre entré dans le corp s
du programme main...
A qui peut aider,
merci
On va voir si on peut essayer¹.
En C, fscanf est une fonction qui retourne un résultat. Ce résultat, tu
ne PEUX PAS faire comme s'il n'existe pas (comme tu pourrais le faire
avec printf): if FAUT vérifier que la fonction a bien fonctionné comme
prévu, et en l'occurrence elle devrait renvoyer 3 (le nombre d'objet
lus), ou encore EOF (si tu es à la fin de fichier au début de la lecture
: avantage, cela économise un appel à feof() ensuite !) ;
une autre valeur doit être prise en compte et annuler le reste du
traitement, cela indique une erreur dans les données.
Une manière de faire est d'écrire :
#include
/* ... */
{
int r;
r = fscanf(FP_DESTI, "%d%s%s", &FTicket, FName, FPren);
if( r == EOF )
break;
assert(r == 3);
Nota : ce n'est pas du code industriel, mais cela suffit amplement pour
ce que tu fais ; on peut aussi écrire
if( r != 3 ) routine_d_erreur("machin", "truc");
mais assert() revient au même au point où tu es (et il n'est point
besoin d'écrire routine_d_erreur ;-) ).
Autre point sans relation, il manque
putchar('n');
à la fin de DisplayRec.
Antoine
_____
¹: on notera que je prend des précautions.
Bah on dirait pas. Tu n'as toujours compris que feof() ne servait pas
à déterminer la fin de lecture. A quoi ça sert qu'on te fournisse des
réponses si tu ne les lit pas ? J'ai indiqué comment on détermine la
fin de lecture. Fait le. Point.
Une fois la fin de lecture détectée (rappel : en testant la valeur
retournée par la fonction de lecture); on peut (mais c'est rarement
utile) déterminer la CAUSE de la fin de lecture en appelant feof() et
ferror(). Mais tout ça, c'est déjà la doc que tu devrais avoir lu. ne
pas se laisser intoxiquer par le nom des fonctions. Le C est un
langage industriel et non universitaire. Il n'a pas pour vocation
d'enseigner la programmation (donc pas du tout un langage de
débutant), mais de faire exactement ce pour quoi il a été conçu. LI RE
LA DOC DE TOUTES LES FONCTIONS AVANT DE LES UTILISER.
Une référence très sûre : http://www.opengroup.org/onlinepubs/79909 89775/
C'est en anglais, bien sûr ...
Et si tu ne comprends pas la doc, demande des explications.