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 :

Problème avec fopen


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Problème avec fopen
    Je débute en C et j'ai un problème avec la fonction "fopen". En fait le projet que je dois faire consiste à gérer des conférences. Je dois donc d'abord charger les données de ces conférences. Les conférences se trouvent dans un fichier "configuration.txt". Dans ce fichier, je lis le nom des conférences qui correspondent aussi à un fichier. Dans ce fichier que je dois ouvrir également, je dois lis les infos sur les conférences (Nom de la conf, date de la conf, etc). Viens alors le pb... si je mets, par exemple, 15 noms de conférences de le fichier initial de configuration, le programme me dira comme quoi "Fp2 == NULL" (il affiche "pas ouvert") ceci pour les 14 premières conférences. Par contre, pour la dernière conférence qu'il lira, il lire et m'affichera correctement les informations de la 15èmeconférence (dernière de la liste). Si vous pouviez me dire comment régler ce pb, ça m'arrangerait...lol. Merci d'avance !

    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
     
    int main()
    {
     
     
        char * config = "configuration.txt";
     
    	char buffer[256];
    	char buffer2[256];
    	char confer[256];
    	FILE *Fp;
    	FILE *Fp2;
    	Fp = fopen (config, "r");
    	while(fgets(buffer, 255, Fp)!= NULL)
    	{
     
    		printf("%s 1\n",buffer);
    		strcpy(confer, buffer);
    		Fp2 = fopen (confer, "r");
    		if(Fp2 == NULL)
    			printf("pas ouvert\n");
    		else
    		{
     
    			while(fgets(buffer2, 255, Fp2)!= NULL)
    			{                  
    				printf("%s\n",buffer2);
    			}
    		fclose(Fp2);
    		}
    	}
        fclose(Fp);
    }

  2. #2
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Tout d'abord :



    Ensuite, quelques remarques.

    Tout d'abord comment est formé ton fichier config : comment sépare tu les noms de tes fichiers qui seront chargés. Ca vient peut être de là.

    Ensuite :

    tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char * config = "configuration.txt";
    D'une façon plus logique il serait mieux de faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char config[] = "configuration.txt";
    Ca ne change certainement rien, mais ça me perturbe !!!

    Ensuite, tu utilise strcpy, utilise strncpy, c'est mieux étant donné que tu connais la taille de ton buffer et puis strcpy a des problèmes de sécurité. (même si tu te fiches de la sécurité, c'est toujours un bon reflèxe). En revanche, avec cette méthode, il te faut absolument mettre le caractère de fin de chaine à la main.

    Quand tu affiches ton buffer, il serait aussi interressant d'afficher la chaine confer et de regarder si effectivement c'est bien ce que tu veux et que ça correspond bien à un fichier qui doit être ouvert.

    Enfin, ta fonction main renvoie un entier, et tu n'a pas définit de return ...

  3. #3
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Ton souci vient du fonctionnement de fgets() [1], en effet si la lecture s'arrete sur la rencontre de ce caractere et non a cause de la taille maximale, ce caractere est present dans la chaine lue.
    Il est donc necessaire, si le caractere '\n' est present dans la chaine lue, de l'enlever. Je te renvoie a la FAQ pour la methode.

    Par contre il y a un autre probleme dans ton code : tu ne test pas si l'ouverture du fichier "configuration.txt" s'est deroule correctement.



    [1] Ceci dit ne change surtout pas de fonction, fgets() est sans aucun doute la bonne methode pour lire des lignes completes.

  4. #4
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par PRomu@ld
    tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char * config = "configuration.txt";
    D'une façon plus logique il serait mieux de faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char config[] = "configuration.txt";
    Ca ne change certainement rien, mais ça me perturbe !!!
    Pourquoi serait-il plus logique d'utiliser un tableau plutot qu'un pointeur sur la chaine ? Vu que cette chaine n'est pas destine a etre modifiable le pointeur est tout aussi bien.
    Par contre, la chaine etant probablement dans une zone memoire non modifiable, il serait preferable de l'indiquer afin de ne pas commettre d'erreur lors d'une eventuel modification du code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    const char * config = "configuration.txt";

  5. #5
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    C'est juste une question de gout. Et puis l'expérience à montré qu'en utilisant le symbole [] au lieu de * permettait de mieux comprendre. Personnellement je n'en suis pas forcément convaincu mais la plupart des formateurs ou professeur le préconisent.

    De plus celà reflète plus le type des chaines de caractère : un tableau de caractère. En C le lien entre pointeurs et tableau est très fort, cependant ce n'est pas le cas dans tous les langages.

  6. #6
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut quelques modfis..
    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
    38
    39
    40
    41
    42
    main()
    {
        char * config = "configuration.txt";
     
    	char buffer[256];
    	char buffer2[256];
    	char confer[256];
    	FILE *Fp;
    	FILE *Fp2;
    	Fp = fopen (config, "r");
    	while(fgets(buffer, 255, Fp)!= NULL)
    	{	
    		printf("%s 0\n",buffer);
    		if (fgets (buffer, 255, Fp) != NULL)
    		{
       			char *p = strchr (buffer, '\n');
       			if (p)
       			{
    				*p = 0;
    			}
    		}
    		printf("%s 1\n",buffer);
    		strcpy(confer, buffer);
    		printf("%s 2\n",buffer);
    		printf("%s 3\n",confer);
    		Fp2 = fopen (confer, "r");
    		printf("test entrée SI\n");
    		if(Fp2 == NULL)
    			printf("pas ouvert\n");
    		else
    		{
     
    			while(fgets(buffer2, 255, Fp2)!= NULL)
    			{                  
    				printf("%s\n",buffer2); // ca affiche la ligne
    			}
    		fclose(Fp2);
    		}
    	}
    	fclose(Fp);
    	return 0;
    }

    J'ai donc modifié le programme comme ce qui m'a été conseillé.
    Pour ce qui est de l'organisation de mes fichiers, pour configuration.txt il y a un retour à la ligne après chaque nom de conférence.
    Pour ce qui est des fichiers conference.txt, c'est la même chose, après chaque information sur la conférence, il y a un passage à la ligne.

    Pour ce qui est de l'ouverture de configuration.txt, jil m'affiche tt ce qui se trouve ds ce fichier mais n'arrive pas à ouvrir les fichiers qu'il lie à pars le dernier de la liste.

    Pour ce qui est de l'utilisation de strncpy, comment je peux savoir le nombre n d'octects que je dois ouvrir ?

  7. #7
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    strncpy, copie n caractères de src vers dest, comme strncpy ne copie pas le caractère de fin de chaine, il faut le copier soit même. Avec strlen tu peux avoir la taille de ta chaine src, donc tu sais combien de caractère tu dois copier.

    Après lecture de ce qu'a marqué gl et d'autres posts, le problème doit venir du fait que fgets copie aussi le caratère de retour à la ligne dans ton buffer. Par conséquent, tu dois l'enlever de ta chaine et ensuite tu peux ouvrir ton fichier. Théoriquement ce que tu as fait devrai le faire ...

    Tu n'a toujours pas testé la bonne ouverture de ton fichier de configuration.

    Dis nous si ça fait toujours la même chose qu'avant ou s'il y a eu des modifications.

  8. #8
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Après modification (retrait du caractère de retour à la ligne), le problème est toujours le même.
    Par contre, je ne vois pas ce que je dois faie quand tu me demandes de tester la bonne ouverture de mon fichier configuration.. :-(
    En tout cas le programme m'affiche les noms des configuration (qui se trouvent dans mon fichier configuration) donc logiquement, l'ouverture est censé se faire correctement, non ?
    Je découvre seulement depuis peu tout ce qui est manipulation d'ouverture et d'écriture de fichier..

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Binouce
    Après modification (retrait du caractère de retour à la ligne), le problème est toujours le même.
    Dans la correction apportee, il ne fallait pas refaire un fgets() avant de supprimmer le caractere \n mais simplement enlever le caractere. En clair, la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (fgets (buffer, 255, Fp) != NULL)
    ne devrait pas etre presente

    Citation Envoyé par Binouce
    Par contre, je ne vois pas ce que je dois faie quand tu me demandes de tester la bonne ouverture de mon fichier configuration.. :-(

    Tester que Fp ne soit pas egale a NULL.

    Citation Envoyé par Binouce
    En tout cas le programme m'affiche les noms des configuration (qui se trouvent dans mon fichier configuration) donc logiquement, l'ouverture est censé se faire correctement, non ?
    Si il n'y a pas de caracteres en trop dans le nom lue (espace, \n, tabulation, etc...), que le fichier existe bien, qu'il est possible de l'ouvrir (droit d'acces, etc.) et si il se trouve bien au bon endroit, normalement oui

    Sinon pourquoi lis-tu le nom de fichier dans buffer avant de le copier dans confer ? Autant utiliser uniquement confer.

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par PRomu@ld
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char * config = "configuration.txt";
    D'une façon plus logique il serait mieux de faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char config[] = "configuration.txt";
    Ca ne change certainement rien, mais ça me perturbe !!!
    Ce qui me perturbe c'est qu'il manque le 'const'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char const * config = "configuration.txt";
    et le non respect du format 8.1, mais bon, j'ai abandonné Borland C, alors on s'y fait... Par contre, si, ça change en se sens que le 2ème cas prend un tableau en mémoire, alors que le premier prend un tableau (en mémoire non modifiable) + un pointeur.
    Ensuite, tu utilise strcpy, utilise strncpy, c'est mieux étant donné que tu connais la taille de ton buffer et puis strcpy a des problèmes de sécurité. (même si tu te fiches de la sécurité, c'est toujours un bon reflèxe). En revanche, avec cette méthode, il te faut absolument mettre le caractère de fin de chaine à la main.
    ce qui n'est pa si simple, et est la raison pour laquelle je déconseille formellement l'usage de strncpy() qui procure une fausse sécurité.

    Je recommande strncat() en veillant bien sûr à ce que la chaine de destination soit suffisament grande (attention, le 'n' inclus le 0 final). On peut aussi écrire sa propre fonction de copie 'sûre'.

    http://emmanuel-delahaye.developpez.com/clib.htm
    Module STR
    Fonction STR_safecopy()

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Problème avec fopen
    Merci de poster du code compilable. On ne sait pas ce que tu as oublié...
    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
     
    Compiling: main.c
    main.c: In function `main_':
    main.c:5: warning: initialization discards qualifiers from pointer target type
    main.c:10: error: `FILE' undeclared (first use in this function)
    main.c:10: error: (Each undeclared identifier is reported only once
    main.c:10: error: for each function it appears in.)
    main.c:10: error: `Fp' undeclared (first use in this function)
    main.c:11: error: `Fp2' undeclared (first use in this function)
    main.c:12: error: implicit declaration of function `fopen'
    main.c:12: warning: nested extern declaration of `fopen'
    main.c:13: error: implicit declaration of function `fgets'
    main.c:13: warning: nested extern declaration of `fgets'
    main.c:13: error: `NULL' undeclared (first use in this function)
    main.c:16: error: implicit declaration of function `printf'
    main.c:16: warning: nested extern declaration of `printf'
    <internal>:0: warning: redundant redeclaration of 'printf'
    main.c:17: error: implicit declaration of function `strcpy'
    main.c:17: warning: nested extern declaration of `strcpy'
    <internal>:0: warning: redundant redeclaration of 'strcpy'
    main.c:28: error: implicit declaration of function `fclose'
    main.c:28: warning: nested extern declaration of `fclose'
    main.c:31: warning: nested extern declaration of `fclose'
    main.c:28: warning: redundant redeclaration of 'fclose'
    main.c:28: warning: previous implicit declaration of 'fclose' was here
    main.c:32:2: warning: no newline at end of file
    Process terminated with status 1 (0 minutes, 0 seconds)
    Remarques et corrections partielles...
    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    /* -ed- Ces headers manquaient */
    #include <stdio.h>
    #include <string.h>
     
    int main(void)
    {
       /* -ed-
        char * config = "configuration.txt";
     
       une chaine n'est pas modifiable. Qualifier avec 'const' */
     
       char const * config = "configuration.txt";
     
       char buffer[256];
       char buffer2[256];
       char confer[256];
       /* -ed- ca en fait des buffers. Je sens qu'il y en a plus que necessaire... */
     
       FILE *Fp;
       FILE *Fp2;
     
       Fp = fopen (config, "r");
       /* -ed- fopen() peut echouer. Dans ce cas, il renvoit NULL. */
     
       if (Fp != NULL)
       {
          /* -ed-
                while (fgets(buffer, 255, Fp) != NULL)
           
                pourquoi 255 ? Il vaut utiliser sizeof qui est fait pour.
          */
          while (fgets(buffer, sizeof buffer, Fp) != NULL)
          {
             printf("%s 1\n", buffer);
     
             /* -ed- pourquoi une copie ?
                     Par contre, il manque un traitement pour retirer le '\n'
                     final.
              */
             strcpy(confer, buffer);
     
             Fp2 = fopen (confer, "r");
             if (Fp2 == NULL)
             {
                /* -ed- message abscons...
                printf("pas ouvert\n");
                */
                perror(confer);
             }
             else
             {
     
                while (fgets(buffer2, 255, Fp2) != NULL)
                {
                   printf("%s\n", buffer2);
                }
                fclose(Fp2);
             }
          }
          fclose(Fp);
       }
       else
       {
          perror(config);
       }
     
       /* -ed- main() retournant int, il faut le faire... */
       return 0;
    }

Discussions similaires

  1. problème avec fopen
    Par Vincent157 dans le forum Visual C++
    Réponses: 1
    Dernier message: 28/06/2007, 14h14
  2. Problème avec fopen
    Par morgan47 dans le forum Langage
    Réponses: 5
    Dernier message: 21/12/2006, 22h47
  3. problème avec fopen
    Par eoberlin dans le forum C++
    Réponses: 10
    Dernier message: 26/08/2006, 20h26
  4. Problème avec fopen
    Par Fonzy007 dans le forum Langage
    Réponses: 2
    Dernier message: 24/07/2006, 18h15
  5. [FTP] Problème avec fopen sur URL
    Par Biboune2008 dans le forum Langage
    Réponses: 14
    Dernier message: 22/06/2006, 17h00

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