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 :

Initialisation d'un pointeur de type 'FILE *'


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut Initialisation d'un pointeur de type 'FILE *'
    Bonjour,
    Je ne comprend pas pourquoi mais à force de diagnostique et de rechcerches depuis plus d'une heure je viens de m'apercevoir qu'un pointeur de type 'FILE *' (peut-être n'est-ce pas le seul type) est initialisé à 0 ('NULL') en présence de déclaration de tableaux de pointeurs (même si cette déclaration est faite quelques lignes en dessous) et initialisé à une valeur (aléatoire à première vue) lorsque qu'aucun tableau de pointeur n'est défini.

    Je ne comprends plus rien d'autant plus que quand je défini ce pointeur grâce à fopen il n'est toujours pas initialisé si des tableaux de pointeurs ont été définis...

    Est-ce que quelqu'un a une explication (simple de préféence, je débute :p) à mon problème?

    Merci!

    EDIT : à titre d'exemple, après avoir basardé tout mon pour trouver le problème voici le bout de code qui m'a permit de faire mon diagnostique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
     
    int main(void)
    {
        FILE * rien;
        if(rien == NULL) printf("Problème\n");
     
        char *pers[6] = {"je", "tu", "il", "nous", "vous", "ils"};
        char *term[6] = {"e", "es", "e", "ons", "ez", "ent"};
     
        return 0;
    }

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 724
    Points
    5 724
    Par défaut
    Est-ce que tu as un exemple de code a proposer pour exposer ton incompréhension.
    " Dis ce que tu veux qui insulte mon honneur car mon silence sera la réponse au mesquin.
    Je ne manque pas de réponse mais : il ne convient pas aux lions de répondre aux chiens ! " [Ash-Shafi'i ]

  3. #3
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 724
    Points
    5 724
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
     
    int main(void)
    {
        FILE * rien;
        if(rien == NULL) printf("Problème\n");
     
        char *pers[6] = {"je", "tu", "il", "nous", "vous", "ils"};
        char *term[6] = {"e", "es", "e", "ons", "ez", "ent"};
     
        return 0;
    }
    Qu'est-ce que tu constates au juste ? rien est une variable locale automatique qui va être empilé sur la pile donc dedans tu peux avoir tout et n'importe quoi si tu ne l'initialises pas. Cela peut être null comme autre chose il n'y a, désolé, a priori aucun mystére.
    " Dis ce que tu veux qui insulte mon honneur car mon silence sera la réponse au mesquin.
    Je ne manque pas de réponse mais : il ne convient pas aux lions de répondre aux chiens ! " [Ash-Shafi'i ]

  4. #4
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    sisi tant qu'au moins un des deux tableaux de pointeurs est toujours déclaré, 'FILE * rien' est initialisé à 'NULL'

    Essaie ensuite en commentant les deux déclarations de tableaux et 'FILE * rien' sera initialisé avec une valeur variable. (en tout cas sous Code::Blocks)

  5. #5
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Lorsqu'on initialise un tableau ou une structure tous les éléments restants non initialisés sont remplis par des 0. Par exemple si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int t[10] = {0, 10, 20, 30, 40};
    t[5], t[6], t[7], t[8] et t[9] seront initialisés à 0.

    Sur x86 les variables locales sont placées sur la pile (donc dernier arrivé, premier sorti). Par exemple si on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int a, b, c, d, e, * p = &e;
    Alors :
    p[0] = e
    p[1] = d
    p[2] = c
    p[3] = b
    p[4] = a

    Et comme dit plus haut, si tu initialises un tableau, tous les éléments restants non initialisés seront initialisés à 0 ... Tout peut arriver (selon le compilateur, le système, etc.). Moi en tout cas (Code::Blocks, Windows XP) j'ai pas ce "phénomène".

  6. #6
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    mais je ne comprend pas bien le rapport entre mes tableaux de pointeur et mon 'FILE * rien'...
    quand j'ai mes tableaux, 'FILE * rien' est TOUJOURS initialisé à 'NULL' tandis que sans les tableaux, il est TOUJOURS initialisé aléatoirement mais jamais 'NULL'...

    en plus quand j'ai mes tableaux, même si je déclare 'FILE * rien' et que je l'initialise après 'rien = fopen(nomfichier, "w")' par exemple, il est dans tous les cas nul...

  7. #7
    Membre Expert

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Points : 5 724
    Points
    5 724
    Par défaut
    Tes tableaux et ton FILE* sont sur la pile ! Par définition une variable locale automatique non initialisée a comme valeur n'importe quoi car on ne peut faire savoir ce qu'il y avait sur la pile avant. Il n'y a pas un petit bonhomme vert caché dans ton micro qui te fait une blague foireuse pour te faire péter les plombs.

    Pour le fopen qui te renvoi NULL c'est que le fichier n'existe pas ou qu'il est impossible de l'ouvrir.
    " Dis ce que tu veux qui insulte mon honneur car mon silence sera la réponse au mesquin.
    Je ne manque pas de réponse mais : il ne convient pas aux lions de répondre aux chiens ! " [Ash-Shafi'i ]

  8. #8
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    donc en fait je déclare 'rien', il se met tout en bas de la pile et dès que d'autres trucs arrivent dans la pile, il est mis à 0?

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Non, rien n'est dit à ce propos sur la pile, il s'agit d'un comportement indéfini il est donc formellement à éviter !

    faire un "= NULL" pour initialiser ta variable ne coûte rien et ça évite de faire des paris idiots que celui que tu veux faire, donc fais-le et tout ira bien.

  10. #10
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    je ne veux justement pas l'initialiser à 0 et il n'y a aucun pari idiot.

    j'avais juste un problème avec ma fonction fclean qui ne s'exécutait pas justement parce que mon 'FILE' était nul
    je peux donc changer ma fonction fclean :
    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
    int fclean (char *s_buffer, FILE * stream)
       {
       int err = 0;
       if (s_buffer != NULL && stream != NULL)
       {
          char *pc = strchr (s_buffer, '\n');
     
          if (pc != NULL)           /* La saisie n'a pas ete tronquee */
          {
             /* On remplace '\n' par le caractere nul '\0' */
             *pc = 0;
          }
       else
       {/* La saisie a ete tronquee, on purge le flux d'entree */
           int c;
           while ((c = fgetc (stream)) != '\n' && c != EOF)
           {
           }
           err = 1;
       }
       return err;
       }
    par la suivante?
    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
    int fclean (char *s_buffer, FILE * stream)
       {
       int err = 0;
       if (s_buffer != NULL)
       {
          char *pc = strchr (s_buffer, '\n');
     
          if (pc != NULL)           /* La saisie n'a pas ete tronquee */
          {
             /* On remplace '\n' par le caractere nul '\0' */
             *pc = 0;
          }
       }
       if(stream != NULL)
       {/* La saisie a ete tronquee, on purge le flux d'entree */
           int c;
           while ((c = fgetc (stream)) != '\n' && c != EOF)
           {
           }
           err = 1;
       }
       return err;
       }
    ce qui me permet plutôt que de déclarer un FILE non nul qui ne sert à rien de lancer fclean avec comme deuxième argument un petit 'NULL'?!

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Bah justement non, tu veux faire exactement ce qu'il ne faut pas faire !
    Tu dois TOUJOURS tester qu'un objet est initialiser ou pas avant d'exécuter une fonction dessus !
    Imagine que tu utilises un fread() sur un fichier dont tu n'as pas initialiser le pointeur, ou qui n'a jamais reçu la valeur de retour de fopen().
    Ta variable contiendra n'importe quelle adresse, et qu'est-ce que ça fera si fread() tente de lire l'adresse toute pourrie que tu lui as donné ? Bah tu auras un segmentation fault !

    C'est pour ça que l'initialisation est importante ! C'est pour détecter si une variable (et surtout un pointeur) est valide !

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    La bonne pratique, c'est de TOUJOURS initialiser un pointeur.
    • Soit avec une addresse valide (retour de malloc(), de fopen() etc.)
    • Soit avec NULL.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    oui oui j'avais bien compris tout ça mais ici le pointeur 'FILE * rien' n'était déclaré que dans l'utilité de la fonction 'fclean()' puisque celle-ci ne nettoie une saisie avec 'fgets()' que si elle a un pointeur non nul en argument en plus de la chaîne de caractères.
    je conviens que c'est pas terrible, voire limite, de faire ce genre de manip mais c'est ce qu'il me faut si je veux éviter l'usage de 'scanf()'

    donc mon changement de la fonction 'fclean()' conviendrait?
    si je n'ai donc pas de pointeur 'FILE *' utile dans mon programme je pourrais donc utiliser 'fclean()' de la façon suivante :

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Je comprends pas ce que tu veux faire...

    Si tu veux nettoyer le flux d'entrer en utilisant ta fonction, pourquoi ne passerais-tu pas à ta fonction les fichiers standards ?
    1. stdin : flux d'entrée
    2. stdout : flux de sortie
    3. stderr : flux pour les erreurs

  15. #15
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    non en fait cette fonction me sert
    soit à nettoyer un flux
    soit à nettoyer le caractère de saut de ligne à la fin d'une saisie via 'fgets()' et dans ce cas il me faut un flux en plus si j'utilise la version originale de 'fgets()' et un flux non nul d'où mon utilisation limite de 'FILE *'

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Pas la peine de faire l'économie de fonction tu sais !
    Fais deux fonctions séparées, une qui nettoie un flux et l'autre qui remplace le caractère finale d'une chaîne de caractères.

  17. #17
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    ben j'utilise la foncton que m'avais donné Emmanuel Delahaye donc j'me suis pas posé de question quant à son efficacité

    donc je peux faire deux fonctions, une pour nettoyer le flux et une pour nettoyer la saisie? en gros deux fonctions qui correspondent aux deux parties de la fonction 'fclean()' actuelle?
    sinon juste à titre indicatif pour mon expérience personnelle, les changement que j'ai fais quelques posts plus haut sur l'originale 'fclean()' sont-ils valables?! ou corrects en tout cas?!

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    308
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 308
    Points : 373
    Points
    373
    Par défaut
    Oui, ton changement est bon, et il justifie d'autant plus la séparation en deux fonctions, puisque la première partie s'occupe de la chaîne de caractère et la deuxième s'occupe du buffer, donc faire une seule fonction pour ces deux processi différent n'a aucun sens.

  19. #19
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Points : 5
    Points
    5
    Par défaut
    ok je fais ça merci!

  20. #20
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si, ça a un sens: On ne fait la purge du FILE* que si le \n n'a pas été trouvé dans la chaîne...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. [JSP]<input type="file">
    Par phoebe dans le forum Servlets/JSP
    Réponses: 13
    Dernier message: 16/07/2012, 19h50
  2. Réponses: 24
    Dernier message: 23/02/2006, 11h04
  3. [<input type="file"/>]
    Par NikoBe dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 27/04/2005, 09h17
  4. [HTML]Utilisation du type file
    Par Kuroro dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 23/12/2004, 16h12
  5. chemin d'un input de type file
    Par sbbn1 dans le forum ASP
    Réponses: 2
    Dernier message: 05/04/2004, 20h19

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