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

fscanf feof et compagnie...

6 réponses
Avatar
bpascal123
Bonjour cyberespace,

Je reprends une discussion dans un nouveau fil pour chercher un
nouveau dynamisme. Voici un fichier texte "ga1.txt":

10
the
vert
20
cafe
noir
30
biere
brune

Maintenant, je souhaite le lire =E0 l'=E9cran avec fscanf et printf. Voici
le code complet :

#include <stdio.h> /* printf, fprintf, scanf, fscanf, getchar, fgetc,
fopen, fclose, feof */
#include <stdlib.h> /* exit */

#define CTXTMAX 30 /* nbr de lettres max. */
#define CNBRECMAX 3 /* nbr d'enreg. max. */

void DisplayRec(FILE *FP_DESTI) ;
void DisplayRec2(FILE *FP_DESTI, int FMat[], char FNom[], char
FPren[], int nmax) ;

int main(void)
{
FILE *MP_DESTI ;
char Filename[] =3D "/media/XP/code_c/ga1.txt" ;
int MMat[CNBRECMAX] ;
char MNom[CNBRECMAX] ;
char MPren[CNBRECMAX] ;

printf("\n*****************************************") ;
printf("\n\nOUVERTURE ET LECTURE ga1.txt\n\n") ;
printf("*****************************************\n") ;

MP_DESTI =3D fopen(Filename, "r") ;
if (!MP_DESTI)
{
printf("\nImpossible d'ouvrir \"%s\".", Filename) ;
exit(1) ;
}

/* DisplayRec(MP_DESTI) ; */

DisplayRec2(MP_DESTI, MMat, MNom, MPren, CNBRECMAX) ;

fclose(MP_DESTI) ;

printf("\n\n") ;
return 0 ;
}

/* cette fonction affiche le tout : alors le fichier est lisible
void DisplayRec(FILE *FP_DESTI)
{
int c ;
printf("\n\nAFFICHAGE : \n") ;
while ( (c =3D getc(FP_DESTI)) !=3D EOF)
putchar(c) ;
}
*/

void DisplayRec2(FILE *FP_DESTI, int FMat[], char FNom[], char
FPren[], int nmax)
{
int i =3D 0 ;
printf("\n\nAFFICHAGE : \n") ;

while (!feof(FP_DESTI))
{
if (fscanf(FP_DESTI,"%d%s%s", &FMat[i], FNom, FPren) !=3D 3)
break ;
else
{
printf("Ticket no %d\nNom : %s\nPrenom : %s\n", FMat[i], FNom,
FPren) ;
i++ ;
}
}
}

DisplayRec2 affiche le nombre FMat comme attendu mais le nom ne veut
pas s'afficher??? En fait, s'affichent en position 1 les dernieres
lettres du prenom, en position 2 les 2 dernieres lettres du prenom et,
en position 3 les 3 derni=E8res lettres du prenom. Je ne comprends pas
ce qui se passe.

Dans le m=EAme sujet, je n'ai pas fait attention jusqu'=E0 pr=E9sent mais
comment =E7a se fait que seulement FMat a besoin d'un indice??? Si
j'ajoute [i] =E0 FNom et FPren, le compilateur cherche que ses arguments
renvoient des nombres entiers dans l'une et l'autre des fonctions
fscanf et printf.
En fait, elles sont incr=E9ment=E9es automatiquement sans l'aide d'un
indice???

Je devais faire une macro vba dans mon travail et les objets vba ont
besoin d'un indice...Mais les variables de types tableaux de caract=E8re
en C sont automatiquement incr=E9ment=E9s? L'adresse du premier indice
FNom[0] equivalent =E0 FNom est automatiquement incr=E9ment=E9e?

Mais si quelqu'un peut vraiment m'aider avec le retour du fscanf, =E7a
serait d'un gros secours. Je ne sais pas si cet indispensable alors
qu'il existe des structures de donn=E9es et que je n'ai pas encore
abord=E9 ce chapitre, je pense encore qu'alors j'arrive dans les choses
plus s=E9rieuses avec le langage c et j'aimerais comprendre avant les
fonctions les plus fr=E9quentes (je ne suis pas s=FBre).

Merci
Fin de question
Planete d=E9butant.

6 réponses

Avatar
Antoine Leca
écrivit :
int MMat[CNBRECMAX] ;



Un tableau d'entiers.

char MNom[CNBRECMAX] ;



*Une* chaîne ; pas très homogène... de plus il n'ya de la place que pour
deux caractères (plus le terminateur).

char MPren[CNBRECMAX] ;



Une autre chaîne de 2+1 caractères.


DisplayRec2(MP_DESTI, MMat, MNom, MPren, CNBRECMAX) ;



On passe l'adresse du tableau d'entiers et des deux chaînes.

void DisplayRec2(FILE *FP_DESTI, int FMat[], char FNom[], char
FPren[], int nmax)



Le prototype est homogène.

{
int i = 0 ;

while (!feof(FP_DESTI)) {



Pourquoi faire ?

if (fscanf(FP_DESTI,"%d%s%s", &FMat[i], FNom, FPren) != 3)



Mmmm... l'entier va bien dans le tableau, les noms et prénoms vont dans
les chaînes de 2+1 caractères... ce qui est trop court.


Je devais faire une macro vba dans mon travail et les objets vba ont
besoin d'un indice...Mais les variables de types tableaux de caractère
en C sont automatiquement incrémentés? L'adresse du premier indice
FNom[0] equivalent à FNom est automatiquement incrémentée?



Un objet String de VBA n'a pas d'équivalent direct en C. Pour suppléer
ce manque, on utilise des tableaux de caractères (Array Of Char), plus
la convention de '' pour enregistrer la longueur de la chaîne ; mais
cela reste un tableau ; pour avoir l'équivalent d'un Array of String, en
C il te faut un tableau de tableau de char, char MNom[LONG][NBRE]


Mais si quelqu'un peut vraiment m'aider avec le retour du fscanf,



Où est le problème ? Ton message ne mentionne rien à ce sujet, outre le
texte du programme et ses données, il parle essentiellement de
structures de données, tableaux ou chaînes. Puis de VBA.


Antoine
Avatar
-ed-
On 31 août, 01:39, ""
wrote:
Bonjour cyberespace,

Je reprends une discussion dans un nouveau fil pour chercher un
nouveau dynamisme. Voici un fichier texte "ga1.txt":



J'ai fait une simplification du code qui montre que la lecture par
fscanf() est correcte, à condition de ne pas utiliser feof() n'importe
comment ... (une fois de plus, on en a pas besoin ici, le test de la
valeur retournée par la fonction de lecture suffit) :

#include <stdio.h> /* printf, fprintf, scanf,
fscanf, getchar, fgetc,
fopen, fclose, feof */
#include <stdlib.h> /* exit */

#define CTXTMAX 30 /* nbr de lettres max. */
#define CNBRECMAX 3 /* nbr d'enreg. max. */

#if 0
/* cette fonction affiche le tout : alors le fichier est lisible */
void DisplayRec (FILE * FP_DESTI)
{
int c;
printf ("nnAFFICHAGE : n");
while ((c = getc (FP_DESTI)) != EOF)
putchar (c);
}
#endif

void DisplayRec2 (FILE * FP_DESTI)
{
printf ("nnAFFICHAGE : n");

while (1)
{
int Mat;
char Nom[32];
char Pren[32];
if (fscanf (FP_DESTI, "%d%s%s", &Mat, Nom, Pren) != 3)
break;
else
{
printf ("Ticket no %dnNom : '%s'nPrenom : '%s'n", Mat,
Nom, Pren);
}
}
}

int main (void)
{
FILE *MP_DESTI;
char Filename[] = "ga1.txt";

printf ("n*****************************************");
printf ("nnOUVERTURE ET LECTURE ga1.txtnn");
printf ("*****************************************n");

MP_DESTI = fopen (Filename, "r");
if (!MP_DESTI)
{
printf ("nImpossible d'ouvrir "%s".", Filename);
exit (EXIT_FAILURE);
}

/* DisplayRec(MP_DESTI) ; */

DisplayRec2 (MP_DESTI);

fclose (MP_DESTI);

printf ("nn");
return 0;

}

Maintenant, si tu veux stocker les données lues et les exploiter
ensuite, il faut créer un tableau de structures.
Avatar
bpascal123
On Aug 31, 8:00 am, Antoine Leca wrote:
écrivit :

>    int MMat[CNBRECMAX] ;

Un tableau d'entiers.

>    char MNom[CNBRECMAX] ;

*Une* chaîne ; pas très homogène... de plus il n'ya de la place que pour
deux caractères (plus le terminateur).

>    char MPren[CNBRECMAX] ;

Une autre chaîne de 2+1 caractères.



Merci,
Je me suis trompé de constante. Erreur d'inattention et comme il n'y a
pas de message d'erreur sur la longueur de la chaine...

Pour le reste, je me demandais juste comment la lecture du fichier
texte pouvait se faire dans une boucle sans incrémentation propre à
chaque variable sauf pour FMat...

Pour reprendre le premier post :
while (!feof(FP_DESTI))
{
if (fscanf(FP_DESTI,"%d%s%s", &FMat[i], FNom, FPren) != 3)
break ;
else
{
printf("Ticket no %dnNom : %snPrenom : %sn", FMat[i], FNom,
FPren) ;
i++ ;
}
}
Comment la lecture de FNom et FPren est incrémentée dans fscanf et
printf. Si je devais dire ce que produit le code, ça serait la
l'affichage :
10
the
vert
20
the
vert
30
the
vert

?

Merci
Avatar
Antoine Leca
écrivit :
Pour le reste, je me demandais juste comment la lecture du fichier
texte pouvait se faire dans une boucle sans incrémentation propre à
chaque variable sauf pour FMat...



La lecture d'un fichier _comporte_ bien une incrémentation : celle du
pointeur (implicite) de position du fichier !
De même, l'écriture à l'écran comporte elle aussi une incrémentation :
on voit bien que les caractères ne se chevauchent pas !


Par ailleurs, la logique des traitements sur des fichiers est de
travailler enregistrement par enregistrement. Pour ce faire, à un
instant donné on a besoin d'un seul enregistrement en mémoire, et donc
l'empreinte mémoire est limitée. C'est le mode habituel de traitement
pour l'informatique de gestion.

C'est différent de la logique des traitements simultanés, où l'ensemble
des données sont chargées en mémoire avant le traitement. Pour ce faire,
il faut effectivement des tableaux, des indices etc. et beaucoup de mémoire.


Antoine
Avatar
Lucas Levrel
Le 1 septembre 2010, Antoine Leca a écrit :

écrivit :
Pour le reste, je me demandais juste comment la lecture du fichier
texte pouvait se faire dans une boucle sans incrémentation propre à
chaque variable sauf pour FMat...



La lecture d'un fichier _comporte_ bien une incrémentation : celle du
pointeur (implicite) de position du fichier !
De même, l'écriture à l'écran comporte elle aussi une incrémentation :
on voit bien que les caractères ne se chevauchent pas !


Par ailleurs, la logique des traitements sur des fichiers est de
travailler enregistrement par enregistrement. Pour ce faire, à un
instant donné on a besoin d'un seul enregistrement en mémoire, et donc
l'empreinte mémoire est limitée. C'est le mode habituel de traitement
pour l'informatique de gestion.

C'est différent de la logique des traitements simultanés, où l'ensemble
des données sont chargées en mémoire avant le traitement. Pour ce faire,
il faut effectivement des tableaux, des indices etc. et beaucoup de mémoire.



Si j'ai bien compris (lu le fil un peu en diagonale), sa question est
beaucoup plus prosaïque : pourquoi FMat[i] mais FNom sans [i] ?

La réponse : le descripteur %s de scanf demande un char*, %d demande un
int*. Le code proposé crée un tableau int FMat[3] dont chaque « case »
(FMat[i]) contiendra, in fine, une des valeurs 10, 20, 30. Le même code
crée deux chaînes de 2 caractères char FNom[3], FPren[3]. FNom est un
pointeur vers le début d'*une* chaîne de caractères, on ne peut pas
stocker trois chaînes dedans ! Le code passe à chaque fois le même
pointeur à scanf, si bien qu'à chaque fois la chaîne précédemment stockée
est écrasée. In fine, FNom ne contient qu'une chaîne, la dernière lue. Le
même comportement serait obtenu pour les valeurs numériques si le code
créait une variable int FMat et passait à scanf &FMat.

Pour stocker plusieurs chaînes il faut un tableau à deux dimensions...
--
LL
Avatar
kikonc
a écrit dans le message de groupe de discussion
:
On Aug 31, 8:00 am, Antoine Leca wrote:
écrivit :




Merci,
Je me suis trompé de constante. Erreur d'inattention et comme il n'y a
pas de message d'erreur sur la longueur de la chaine...



Il ne peut y avoir de message d'erreur.
Il est impossible au compilateur de déterminer que la longueur que tu
indiques pour la chaîne, est en fait, fausse.



Pour le reste, je me demandais juste comment la lecture du fichier
texte pouvait se faire dans une boucle sans incrémentation propre à
chaque variable sauf pour FMat...



Il n'y pas d'incrémentation pour FNom, et FPren.
La lecture des valeurs numériques va remplir le tableau FMat cellule après
cellule, grâce à l'incrémentation de l'indice.
La lecture de des deux autre champs vont se faire toutes, enregistrement
après enregistrement au même endroit, dans FNom et dans FPren

A la fin de ta boucle, quand tu auras parcouru tout le fichier.
Tu auras la possibilité d'accéder un élément quelconque dans le tableau FMat
:
- à l'indice 0 tu vas trouver la valeur 10
- à l'indice 1 tu vas trouver la valeur 20
- ....

Dans les variable FNom et FPren, tu n'auras QUE les valeurs du dernier
enregistrement lu, c'est à dire 'biere' et 'brune'.