IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

lecture de fichier C


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Janvier 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Janvier 2017
    Messages : 4
    Points : 2
    Points
    2
    Par défaut lecture de fichier C
    Bonjour,


    Je veux lire un fichier qui a le format suivant:

    chaine de 30 caracteres pour le nom, suivi d'un float, suivi d'un float
    Exemple:

    sylvie pierre 2,5 3,40
    marie claude 3,1 10
    pierre carl 10 12

    Au début, j'ai fait le code que vous allez voire plus bas mais le résultat retourné n'est pas bon.
    J'ai réussi à lire le fichier en utilisant un autre code (en utilisant seulement fscanf) mais ma question est pourquoi le code suivant ne permet pas de lire les données correctement?

    Voilà le code réalisé, l'idée est de lire la chaine de 30 caractères et ensuite de lire le reste de la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	while(fgets(tmpNom,30, fichEmp  )!= NULL)
    	{
    		fscanf(fichEmp, "%c %f %f\n", &tmpPoste, &tmpTauxH, &tmpHeureS );			
    				printf("**** %s\n", tmpNom);
    				printf("-----%c %f %f\n", tmpPoste, tmpTauxH, tmpHeureS);
     
    			}

    Le resultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    **** Tremblay Alain
    -----  0.000000 0.000000
    **** A 35.0 35.5
     
    -----V 0.000000 0.000000
    **** achon Jean
    -----P 40.000000 22.750000
    **** Lapalme Justin
    -----  40.000000 22.750000
    **** O 40.0 15.75
     
    -----D 40.000000 22.750000
    **** eschenes Sylvie
    -----P 35.000000 25.000000
    **** Lachance Carl
    -----  35.000000 25.000000
    **** O 37.5 18.0
     
    -----  35.000000 25.000000
    Merci

  2. #2
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Vérifie le retour de ton fscanf, ton code est faux à cet endroit là je pense, mais honnêtement il vaut mieux:

    - Utiliser fgets pour lire toute la ligne
    - Ensuite à partir du 30ème caractère utiliser strtof pour faire ce que tu veux et faire de la vérification d'erreur

  3. #3
    Membre extrêmement actif Avatar de nikau6
    Homme Profil pro
    Inscrit en
    Février 2008
    Messages
    402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Février 2008
    Messages : 402
    Points : 728
    Points
    728
    Par défaut
    Déja, la il y a un probleme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(fgets(tmpNom,30, fichEmp  )!= NULL)
    fgets va lire toute la ligne ou num-1 caractères.
    Les noms et prénoms que tu donnes en exemple ne font pas 29 caractères ( 30 - 1 pour nul de fin de ligne) . Peut être les as tu écrit dans le fichier á partir d'un tableau de 30 char (char[30]), mais les noms ne prendront pas la place de 30 caractères pour autant dans le fichier, pas en mode texte.

    Par exemple cette ligne "sylvie pierre 2,5 3,40", fait 23 caractères. Ce qui veut dire que tu vas remplir tmpNom avec toute la ligne, chiffres compris, et le stream du fichier va se déplacer au début de la ligne suivante. Et ensuite tu cherche á lire les nombres avec fscanf, c'est pas bon.

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fscanf(fichEmp, "%c %f %f\n", &tmpPoste, &tmpTauxH, &tmpHeureS );
    Le formateur %c ne lit qu'un seul caractère. Essaye avec %s et tmpPoste.

    Quelque chose m'échappe dans ton fgets() suivi de fscanf(). Tu peux tout lire avec fscanf(). Cette entrée de la FAQ devrait t'aider : http://c.developpez.com/faq/?page=St...-une-structure

  5. #5
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Ce n'est pas un problème d'utiliser fgets pour lire partiellement la ligne. saghaagenc a dit au début que sa chaîne faisait 30 caractères donc ce n'est pas un souci. Je pense que le problème vient plutôt de quelques suppositions:

    - La chaîne de 30 caractères, y-a-t-il un '\0' dans les 30?
    - Sans relire la page man, il me semble que fgets va s'arrêter dans ton cas u 29ème caractère et ajouter un '\0' à la chaîne

    - Ensuite pourquoi le %c pour le fscanf est une bonne question: cela n'était pas présenté dans ta ligne exemple

    Enfin et malgré le fait que tu peux faire un fgets + fscanf comme tu le dis, je pense vraiment qu'un seul fgets avec ensuite une copie des 30 premiers caractères et deux strtof avec les vérifications d'erreurs est plus sûr que ce que tu es en train de faire.

  6. #6
    Membre extrêmement actif Avatar de nikau6
    Homme Profil pro
    Inscrit en
    Février 2008
    Messages
    402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Février 2008
    Messages : 402
    Points : 728
    Points
    728
    Par défaut
    Citation Envoyé par fearyourself Voir le message
    Ce n'est pas un problème d'utiliser fgets pour lire partiellement la ligne. saghaagenc a dit au début que sa chaîne faisait 30 caractères donc ce n'est pas un souci. Je pense que le problème vient plutôt de quelques suppositions:
    Il dit que les chaines font 30 chars mais les exemples qu'il montre sont différents. Pour que les chaines fassent 30 chars il faudrait qu'il rajoute par exemple des espaces á la fin. Ce qui ne semble pas être le cas. Je pense que peut être il s’embrouille concernant la taille des chaines nom et prenom, ou alors les exemples qu'il montre ne sont pas exacts.

    exemples qu'il donne :
    sylvie pierre 2,5 3,40
    marie claude 3,1 10
    pierre carl 10 12

    exemple pour faire 30 chars avec padding:
    sylvie pierre <----------------------------> 3.4 5.6

    Ne pas oublier également que fgets garde le char de fin de ligne '\n' et lit n-1 chars pour le '\0' de fin de ligne. Les chaines doivent donc faire 29 chars max.

    Le plus simple et le plus performant dans ce genre de situation c'est de lire chaque ligne avec 1 appel á fscanf :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    FILE* stream;
    char nom[24] = {0};
    char prenom[24] = {0};
    float f1, f2;
     
    fscanf(stream, "%s%s%f%f\n", nom, prenom, &f1, &f2);
     
    char nom_et_prenom[48] = {0};
    sprintf(nom_et_prenom, "%s %s", nom, prenom);
    Le plus robuste c'est de faire comme 'fearyourself' dit.

  7. #7
    Membre régulier
    Homme Profil pro
    Autres
    Inscrit en
    Août 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Autres

    Informations forums :
    Inscription : Août 2008
    Messages : 39
    Points : 82
    Points
    82
    Par défaut
    Attention aux specificateurs de format. %s pour une chaine et non %c.

    Attention également à la lecture de fichier que tu fais, quand tu passes avec fgets ton curseur ce deplace à la ligne suivante dans ton fichier. Il faut reprendre ton code.

  8. #8
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Janvier 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Janvier 2017
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses.

    J'ai dû, malheureusement, ajouter de la confusion en voulant simplifier mon fichier.
    En fait le vrai format du fichier suit bien la logique du code, c'est à dire le fichier est bel et bien formé par:
    chaine de 30 caractères (qui pourrait inclure des espaces pour occuper 30 caractères), suivi d'un char, suivi d'un float, suivi d'un float

    Voilà un extrait réèl du fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sylvie pierre               m 2,5 3,40
    marie claude                P 3,1 10
    pierre carl                 p 10 12
    Désolée pour la confusion. Je sais bien qu'on peut faire la lecture du fichier avec fgets et ceci fonctionne bien chez moi.
    Mais ma question, pourquoi le mixage des deux fscanf et fgets ne permet pas de lire correctement les données. Je n'arrive pas jusqu'à présent à comprendre la raison.

    Merci

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Déjà, les nombres flottants ont besoin d'un '.' et non une ',':

    sylvie pierre m 2,5 3,40
    marie claude P 3,1 10
    pierre carl p 10 12
    En:
    sylvie pierre m 2.5 3.40
    marie claude P 3.1 10
    pierre carl p 10 12
    Ensuite la vrai raison est sûrement que tu as un caractère qui est soit en trop ou se fait manger par un des deux. As-tu un petit code, compilable, qu'on peut voir et tester?

  10. #10
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Janvier 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Janvier 2017
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    voila le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define taille 31
     
    void main()
    {
    		FILE* fichEmp;
    		fichEmp=fopen("./info.txt","r");		
    		char tmpNom[taille]="";
    		char tmpPoste;
    		float tmpTauxH, tmpHeureS;		
     
    		if(fichEmp==NULL)
    		{
    			printf("impossible d'ouvrir le fichier");
    			exit(1);
    		}
    		else
    		{			
    			while(fgets(tmpNom,30, fichEmp  )!= NULL)
    			{
    				fscanf(fichEmp, "%c %f %f\n", &tmpPoste, &tmpTauxH, &tmpHeureS );
    				printf("**** %s\n", tmpNom);
    				printf("-----%c %f %f\n", tmpPoste, tmpTauxH, tmpHeureS);				
    			}
    		}
     
     
     
    	fclose(fichEmp);
     
     
    }

    Le fichier info.txt que j'utilise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sylvie pierre                 m 2.5 3.40
    marie claude                  p 3.1 10
    pierre carl                   p 10 12

    Le résultat que j'obtiens et que je n'arrive pas à expliquer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    **** sylvie pierre
    -----  0.000000 -1.#QNAN0
    **** m 2.5 3.40
     
    -----m 0.000000 -1.#QNAN0
    **** arie claude
    -----p 3.100000 10.000000
    **** pierre carl
    -----  3.100000 10.000000
    **** p 10 12
    -----  3.100000 10.000000

  11. #11
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Voilà

    C'est parce que, comme tout le monde a dit ici: bien que c'est possible de mettre un fgets avec un fscanf, c'est une source d'erreur. Ton erreur est qu'en fait: fgets ne lit pas toute la ligne et laisse donc un caractère vide pour le fscanf qui suit.

    Du coup, après cela, tout se plante...

    A) Si tu vires un caractères à ta chaîne de 30 caractères, tu as un code qui fonctionne
    B) Si tu ajoutes 1 à la taille de ton tableau et à la fonction fgets, tu as un code qui fonctionne
    - Je suggères B en fait

    Ensuite, ton code a plusieurs remarques si tu veux corriger un peu ton code. Plus ou moins dans l'ordre d'importance ou que les personnes discutent et sont des questions de goût:
    1. Utilises QUE fgets comme je l'ai déjà dit ;-)
    2. main retourne int avec un joli EXIT_SUCCESS à la fin
    3. exit(1) -> return EXIT_FAILURE
    4. fgets(tmpNom, sizeof(tmpNom), fichEmp) est mieux
    5. si tu vas mélanger déclarations et code, fait FILE* fichEmp = fopen("./info.txt", "r"); au lieu de deux lignes
    6. vérifie le retour de fscanf
    7. vire les espaces avant le ')' du gets et ajoute un espace après
    8. ajoute des espaces autour du == pour fichEmp==NULL
    9. le C a plus la convention de faire fich_emp que fichEmp
    10. "Impossible" est mieux que "impossible"
    11. pas besoin du else si tu exit dans le if
    12. bonne habitude est de faire fclose(fichEmp), fichEmp = NULL;
    13. pas besoin de mettre tmp devant tout, nom, poste, taux,heure
    14. mettre toute la boucle dans une fonction qui prend un paramètre qui est le fichier ouvert
    15. faire une fonction qui mets l'ouverture et vérification d'erreur dans une fonction
    16. avec 13 + 14, tu as donc pour le main:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int main() {
      FILE *fich_emp = ouvre("./info.txt");
      if (!fich_emp) {
         // Pas besoin de dire quelque chose, ouvre envoie un message d'erreur.
         return EXIT_FAILURE;
      }
      parcours_fichier(fich_emp);
      return EXIT_SUCCESS;
    }

  12. #12
    Membre régulier
    Homme Profil pro
    Autres
    Inscrit en
    Août 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Autres

    Informations forums :
    Inscription : Août 2008
    Messages : 39
    Points : 82
    Points
    82
    Par défaut
    Je te fais pas tout, juste te règle une partie d'affichage.
    Il te faut résoudre les lignes vides comme la premiere de ton fichier texte.
    Par exemple, pour que ton code fonctionne, supprime la premiere ligne vide et ton code va fonctionner.

    Voici mon rajout à ton code, un simple espace.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define taille 31
     
    void main()
    {
    		FILE* fichEmp;
    		fichEmp=fopen("./info.txt","r");		
    		char tmpNom[taille]="";
    		char tmpPoste;
    		float tmpTauxH, tmpHeureS;		
     
    		if(fichEmp==NULL)
    		{
    			printf("impossible d'ouvrir le fichier");
    			exit(1);
    		}
    		else
    		{			
    			while(fgets(tmpNom,30, fichEmp  )!= NULL)
    			{
    				fscanf(fichEmp, " %c %f %f\n", &tmpPoste, &tmpTauxH, &tmpHeureS ); // Ici avant le "%c tu mets un espace comme dans l'exemple. 
    				printf("**** %s\n", tmpNom);
    				printf("-----%c %f %f\n", tmpPoste, tmpTauxH, tmpHeureS);				
    			}
    		}
     
     
     
    	fclose(fichEmp);
     
     
    }

  13. #13
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Janvier 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Janvier 2017
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Bien, je comprends maintenant.
    Merci pour tous vos commentaires

  14. #14
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par debut_c Voir le message
    Voici mon rajout à ton code, un simple espace.
    Pourquoi rajouter un espace à fscanf quand corriger fgets serait mieux? Le souci de l'espace à fscanf est que cela va rendre le debuggage et le code plus compliqué....

  15. #15
    Membre régulier
    Homme Profil pro
    Autres
    Inscrit en
    Août 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Autres

    Informations forums :
    Inscription : Août 2008
    Messages : 39
    Points : 82
    Points
    82
    Par défaut
    Je l'aide sur la fonction qu'il utilise, scanf est tres puissant du moment qu'on connais son fonctionnement. Il peut tres bien faire avec et maitriser son fichier texte.
    Maintenant si il prefere utiliser fgets pas de soucis, il fait son choix.

    Edit : Il posé la question du fonctionnement de fgets et fscanf en meme temps.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Windows]lecture des fichier lnk (raccourcis)
    Par Tiaps dans le forum API standards et tierces
    Réponses: 10
    Dernier message: 21/10/2009, 19h27
  2. [jsp]lecture de fichier
    Par antigone dans le forum Servlets/JSP
    Réponses: 9
    Dernier message: 04/09/2003, 11h05
  3. [AS400][Intranet][PC] Lecture de "fichiers" AS400
    Par lando dans le forum Autres SGBD
    Réponses: 4
    Dernier message: 16/07/2003, 11h11
  4. Lecture de fichier
    Par Watcha dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 04/03/2003, 20h43
  5. Lecture de fichiers ".WAV"...
    Par 0x4e84 dans le forum Langage
    Réponses: 2
    Dernier message: 03/09/2002, 09h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo