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 :

detection de la fin de fichier


Sujet :

C++

  1. #1
    Nouveau candidat au Club
    Inscrit en
    Juillet 2010
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 1
    Par défaut detection de la fin de fichier
    Salut,

    En fait je dois faire un programme qui lit un fichier d'entiers (la premiere ligne est une ligne de caractere) et qui recopie certaines de ces valeurs dans un autre fichier.
    Mon probleme est la boucle while qui va lire toutes les lignes du fichier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    if (fichier)
    	{		
    		char blabla[5],tata[5],sat[5],xas[5],yar[5],bar[5],qar[5],par[5];
    		fichier>>blabla>>tata>>sat>>xas>>yar>>bar>>qar>>par;
    		int index ,al ,type,hdm,ac,grad_al,grad_ac,flux;	
    		while(!feof);
    		{				
    			fichier >> index >> al >> type >> hdm >> ac >> grad_al >> grad_ac >> flux;			
    			cout<<al<<endl;
    			fprintf(newfile,"circle( %d ,%d ,30 ) # color= blue \n",al,ac);	
    		}
    		cout<<"c bon"<<endl;
    		fichier.close(); 
    	}
    merci....

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Bonjour,

    lorsque vous donnez du code sur plusieurs lignes merci de mettre le mettre entre des balises CODE

    Citation Envoyé par astro94 Voir le message
    while(!feof);
    il y a là 2 erreurs
    • le ';' fait que la boucle à un corps vide (et qui n'est donc pas le bloc {} qui suit)
    • feof étant la fonction C, elle n'a aucune chance d'être nulle


    bizarre aussi ce mélange entre les iostream et stdio
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    la_tupac
    Invité(e)
    Par défaut
    Non c'est pas bizard c'est classique du débutant en C et qui migre doucement vers le ++. Mais Bruno a raison stdio est du C et le plus simple c'est d'utiliser fstream (C++)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <fstream>
     
    ofstream MonFichier;
    MonFichier.open("fichier.txt");
    MonFichier << "le nombre est" << nombre << endl;
    MonFichier.close();
    La ref cplusplus : http://www.cplusplus.com/reference/iostream/ofstream/

    courage !

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut, et bienvenue sur le forum
    Citation Envoyé par la_tupac Voir le message
    Non c'est pas bizard c'est classique du débutant en C et qui migre doucement vers le ++. Mais Bruno a raison stdio est du C et le plus simple c'est d'utiliser fstream (C++)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <fstream>
     
    ofstream MonFichier;
    MonFichier.open("fichier.txt");
    MonFichier << "le nombre est" << nombre << endl;
    MonFichier.close();
    La ref cplusplus : http://www.cplusplus.com/reference/iostream/ofstream/

    courage !
    A vrai dire, il y a même encore plus simple: profiter du RAII (Ressource Acquisition Is Initialization) et de son effet contraire...

    En effet, l'un des constructeurs de *fstream admet comme premier paramètre, le nom du fichier à ouvrir, et, lorsqu'une instance de *fstream est détruite, le fichier est automatiquement fermé.
    Nous pourrions donc parfaitement envisager un code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void foo()
    {
        std::ifstream ifs("fichier_d_entree.txt"); //automatiquement ouvert
        /*... */
    } // ifs est détruit (parce que l'on sort de la portée dans laquelle il 
      // est déclaré) et donc fermé :D
    De même, il existe un opérateur de conversion de *fstream en booléen, qui renvoie vrai tant que le flux est dans un état valide (et donc tant que l'on peut tenter une lecture suivante)

    Une boucle de lecture classique dans un fichier pourrait donc prendre une forme "toute simple" proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void foo()
    {
        std::ifstream ifs("fichier_d_entree.txt"); //automatiquement ouvert
        while(ifs)
        {
            /*effectuer la lecture ici */
        }
    } // ifs est détruit (parce que l'on sort de la portée dans laquelle il 
      // est déclaré) et donc fermé :D
    Par contre (je reviens sur le code original de astro94), il est toujours préférable d'éviter le recours aux chaines de caractères "C style" (et, de manière générale, à toute possibilité issue du C) à chaque fois que l'on peut, au profit de l'utilisation de la classe string, disponible dans l'espace de noms std (ou de toute possibilité propre du C++).

    Les chaines de caractères C style présentent en effet une multitude de problèmes, allant du risque d'oublier d'ajouter le '\0' en fin de chaine aux problèmes de tailles et ou de libération de la mémoire, et les possibilités propres au C++ sont généralement plus sécurisantes que leur équivalent en C.

    De plus, même si ce n'est qu'un avis personnel, je préfère éviter de déclarer plus d'une variable par ligne...

    Cela ne change rien, au niveau de l'exécutable, d'utiliser cinq lignes pour déclarer autant de variables, mais cela facilite énormément la relecture par la suite, en évitant de faire passer une (ou plusieurs) déclarations "au bleu".

    Le code original serait donc avantageusement modifié en quelque chose proche de
    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
    void function(std::string const  & filename)
    {
        std::ifstream fichier(filename.c_str()); //ouverture du fichier de lecture
        std::ofstream newfile("sortie.txt")
        if (fichier)
        {		
            std::string blabla;
            std::string tata;
            std::string sat;
            std::string xas;
            std::string yar;
            std::string bar;
            std::string qar;
            std::string par;
            fichier >> blabla >> tata
                    >> sat >> xas
                    >> yar >> bar
                    >> qar >> par;
            int index;
            int al;
            int type;
            int hdm;
            int ac;
            int grad_al;
            int grad_ac;
            int flux;	
            while(fichier);
            {				
                fichier >> index >> al 
                        >> type >> hdm 
                        >> ac >> grad_al
                        >> grad_ac >> flux;			
                 std::cout <<al << std::endl;
                 newfile << "circle("<<al<<","<<ac
                         <<",30) # color: blue"<<std::endl;
            }
            cout<<"c bon"<<endl;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    la_tupac
    Invité(e)
    Par défaut
    Merci mais je ne suis pas nouveau (même si je ne suis pas très actif )
    Très bon post au passage. Mais ce que tu veux dire c'est qu'en ouvrant le fichier dans le constructeur, on a plus besoin de le close() ? Parce-que j'ai déjà rencontré des soucis de ofstream non crée, simplement car je n'avais pas géré le close(). En tout cas si la réponse est oui, il faudra s'assurer que le destructeur est bien appelé. C'est pas forcément évident dans le cas de classes dérivées ...

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    On n'a déjà pas besoin de close de manière générale, à moins que l'on ne veuille fermer explicitement le fichier alors que l'instance du flux existe encore.

    Si tu crées une classe ou une structure dont un des membre est un flux de fichier, cela implique, effectivement, que le fichier ne sera fermé que... lorsque l'instance de la classe ou la structure en question sera détruite (et donc que le flux fichier membre sera lui aussi automatiquement détruit).

    Tu pourrais donc avoir des problèmes avec des classes proches de
    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
    class Reader
    {
        public:
            Reader(std::string const & filename_):ifs(filename_.c_str()){}
            void read(/*...*/);
        private:
            std::ifstream ifs;
    };
    class Writer
    {
        public:
            Writer(std::string const & filename_):ofs(filename_.c_str()){}
            void write(/*...*/);
        private:
            std::ofstream ofs;
    };
    si tu essaye de créer une instance de chaque classe avec le même nom de fichier dans une même portée, soit quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
        Reader rd("monfichier.txt"); // crac : le fichier est ouvert une première fois
        Writer wt("monfichier.txt"); // boum : le fichier ne peut être ouvert une
                                     // deuxième fois
        /*...*/
        return 0;
    }
    Et ce sera encore plus criant si les classes entrent dans une hiérarchie d'héritage, car les instances seront classiquement créées de manière dynamique, et nécessiteront donc une destruction explicite (avec delete).

    Mais il faut aussi comprendre que cela peut demander énormément de ressource de maintenir un flux ouvert, et donc qu'il est préférable que les instances de flux n'existent, quoi qu'il en soit, que le moins longtemps possible.

    C'est la raison pour laquelle l'idéal reste de ne maintenir dans ces classes que... le nom du fichier, et de ne créer le flux que... dans la fonction qui en a besoin:
    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
    class Reader
    {
        public:
            Reader(std::string const & filename_):filename_(filename_){}
            void read(/*...*/) 
            {
                std::ifstream ifs(filename_.c_str());
                /* processus de lecture */
            } // le fichier sera bien fermé en fin de fonction :D
        private:
            std::string filename_;
    };
    class Writer
    {
        public:
            Writer(std::string const & filename):filename_(filename){}
            void write(/*...*/) const
            {
                std::ofstream ofs(filename_.c_str());
                /* processus d'écriture */
            }// le fichier sera bien fermé en fin de fonction :D
        private:
            std::string filename_;
    };
    et tu n'aura donc plus le moindre problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
        Reader rd("monfichier.txt"); // OK : aucun fichier n'est ouvert
        Writer wt("monfichier.txt"); // idem
        rd.read(/*...*/); /* aucun problème: le fichier est ouvert et refermé 
                            * de manière automatique
                            */
        wt.write(/*...*/); // idem
     
    }
    J'en profite pour rappeler qu'une saine pratique consiste à ne demander des ressources que lorsque l'on en a réellement besoin, hein

    PS :le bienvenue sur le forum s'adressait en réalité à astro94
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    la_tupac
    Invité(e)
    Par défaut
    lol ok bienvenu, astro94 .
    C'est bien le soucis que j'avais avec un log que j'ouvrait dans le constructeur et qui n'était pas tout le temps delete(). J'ai fini par créer une fonction qui ouvrait en append, écrivait puis fermait le flux immédiatement. Ca permet de garder le flux fermé le plus souvent possible. Ca rejoint ce que tu disais à l'instant. En tout cas, c'est le genre de concepts obscures pour les débutants qui sortent du C. J'ai longtemp regrété d'avoir commencé en C pour ce genre d'éxamples ...

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Dans l'absolu, rien n'empêche d'ouvrir le fichier dans le constructeur, et de garder le pointeur vers la classe de log quelque part sous le coude...

    Il faut alors s'assurer que l'instance de la classe de log ne soit créée qu'une fois et de bien récupérer chaque fois le pointeur existant

    Un autre problème auquel tu étais sans confronté était d'ailleurs sans doute une fantastique fuite mémoire, non

    Si problème il y a, ce sera plus certainement lorsque tu essayera d'accéder au fichier de log alors que l'application tourne encore, parce que le système d'exploitation risque de considérer le fichier comme inaccessible du fait qu'il est ouvert

    Mais cela confirme ce que je disais plus haut: il est sain de veiller à ne garder une ressource que le temps dont on en a besoin
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    la_tupac
    Invité(e)
    Par défaut
    Effectivement, ça génèrait une bonne fuite mémoire à la fermeture.
    Mais la solution d'ouvrir brièvement le fichier résouds tout les problèmes sauf un : si le fichier est ouvert pendant que l'appli tourne, rien n'est écrit par l'appli. Il faut aussi noter qu'il est moins dangereux de faire ainsi car en cas de coupure de courant ou de plantage, panne de HDD ... il vaut mieu qu'il y'ai le moins de fichiers ouverts pour éviter les chkdsk /r (ou fsck, je préfère )

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par la_tupac Voir le message
    Effectivement, ça génèrait une bonne fuite mémoire à la fermeture.
    Mais la solution d'ouvrir brièvement le fichier résouds tout les problèmes sauf un : si le fichier est ouvert pendant que l'appli tourne, rien n'est écrit par l'appli.
    Et encore, il est *assez facile* de mettre en place un système qui contourne le problème...
    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
    void Writer::write(/*...*/)
    {
        std::ofstream ofs(filename_)
        if(ofs) // true uniquement si le fichier est ouvert
        {
        }
        else // tous les cas où le fichier n'est pas près pour une opération
              // d'entrée / sortie que l'on peut tester séparément
        {
            stdd::ios_base::iostate flag=ofs.rdstate();
            switch(flag)
            {
                 case std::ios_base::eofbit :
                     //fin de fichier atteinte
                     break;
                 case std::ios_base::badbit :
                     //...
                     break;
                 case std::ios_base::failbit :
                     // ...
                     break;
            }
        }
    }
    Typiquement, l'échec de l'ouverture placerait failbit à true.

    Il suffirait de faire en sorte de réessayer plus tard
    Il faut aussi noter qu'il est moins dangereux de faire ainsi car en cas de coupure de courant ou de plantage, panne de HDD ... il vaut mieu qu'il y'ai le moins de fichiers ouverts pour éviter les chkdsk /r (ou fsck, je préfère )
    [/QUOTE]Et, sans aller aussi loin, le fait que le fichier soit ouvert par une application peut déjà empêcher d'y accéder avec une autre, ce qui peut être embêtant pour le fichier log d'une application tournant en permanence (demon ou service, selon l'OS)...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    la_tupac
    Invité(e)
    Par défaut
    Ahhh! les chkdsk /r comme j'en bouffe dans mon petit S.A.V
    Au passage pour les gars qui tomberons dessus en cherchant sur googl, je vous conseille de visiter :
    http://ubuntu-fr.org un petit "big up" mais je pense à vous les autres

    Soyons serieux, il est terrible ton p'tit code je l'ajoute di suite dans mes codes ! (sauf si copyright )
    Pour conclure c'est important de logger les evenements de fichiers, le disque dur est tellement instable ... à garder sous le coude merci
    Dernière modification par Domi2 ; 23/03/2012 à 22h47.

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Bah, tu sais, je n'ai déjà donné que des parties de code, et celles que je présente peuvent à peu près toutes être trouvée par ailleurs, car ce sont des exemples "classiques"

    Maintenant, une petit "thanks to" n'est pas de refus
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Apposer le caractere de fin de fichier.
    Par moldavi dans le forum Windows
    Réponses: 2
    Dernier message: 17/02/2005, 14h20
  2. "error : fin de fichier inattendue" en C++
    Par mateo.14 dans le forum MFC
    Réponses: 9
    Dernier message: 28/01/2005, 09h30
  3. Réponses: 4
    Dernier message: 07/12/2004, 08h11
  4. [CLOB] Détection caractère de fin
    Par SheikYerbouti dans le forum Entrée/Sortie
    Réponses: 6
    Dernier message: 26/08/2004, 17h15
  5. Lire de la 2eme ligne à la fin du fichier
    Par iamspacy dans le forum Linux
    Réponses: 3
    Dernier message: 03/05/2004, 13h23

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