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 fichier et classement des données


Sujet :

C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut lecture fichier et classement des données
    Bonjour tous,

    J'ai un petit programme à faire pour jeudi mais je rencontre de grosses difficultés car je n'ai pas l'habitude du C++ et de la manipulation des chaines de caractères, c'est pour cela que je vous sollicite.

    Je dois faire un debut de programme où le main.cpp nous renvoi à une fonction input qui permettra de lire un fichier texte (de taille variable) et classer les objets dans des vecteurs (<vector>):

    Voici mon fichier texte (exemple):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # matrix name lattice_parameter atomic_volume
    matrix ferrite 2.85 1e-30
    matrix aluminium 1.85 1.2e-30
     
    #precipitate name lattice_parameter atomic_volume 
    precipitate VC 4.1
    precipitate Mg2Si 4
    precipitate Mg5Si6 4.7
     
    #element name stoechiometrique coeff
    Mg2Si 2 1
    Voici mon main.cpp (je ne sais pas trop comment allouer la memoire dynamique et en meme temps renvoyer le contenu du fichier txt à une fonction):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include "input.h"
    using namespace std;
    int *dataBase = NULL;
    int main(int argc, char **argv)
    {
        *dataBase = new string("dataBase.txt");
        input(&dataBase);
        delete dataBase;
        return 0;
    }
    Voici mon input.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifndef INPUT_H
    #define INPUT_H
    #include <string>
    void input(std::string *dataBase);
    #endif
    Voici mon input.cpp :
    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
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include "input.h"
    using namespace std;
    vector <string> matrix;
    void input(string *dataBase)
    {
        string command,dump;
        *dataBase.open(*dataBase.c_str(),ios::in);
        while (!dataBase.eof())
        {
        *dataBase >> command;
            if(!dataBase.eof())
            {
                if(command=="#")
                {
                    getline(dataBase,dump); cout << dump << endl;
                }
                if(command=="matrix");
                {
                      string MatrixName;
                      double LatticeParameter, AtomicVolume;
                      cout << "Matrix command invoqued"  << endl;
                      command >> MatrixName;
                      command >> LatticeParameter;
                      command >> AtomicVolume;
                      *matrix = new Matrix(MatrixName, LatticeParameter, AtomicVolume);
                      matrix.push_back(_matrix);
                      cout << MatrixName << endl;
                      cout << matrix.size() << endl;
                }
                if(command=="precipitate");
                {
                       //ici je veux mettre le nom et nombre dans un vecteur
                       //mais ca sera comme au dessus pour matrix
                }
                if(command=="element");
                {
                        //ici je veux mettre le nom et nombre dans un vecteur
                       //mais ca sera comme au dessus pour matrix
                }
            }
    }
        dataBase.close();
    }
    mais franchement je suis perdu

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    j'ai apporté quelques modif à mon premier message car je me suis rendu compte qu'il y avait des erreurs (mais il en reste encore pas mal je pense )

    ==> En fait mon probleme est double:

    1°) j'ai l'impression que pour faire ce que je veux il n'y a pas besoin de faire plus de chose qu'une fonction (sous matlab j'ai deja fait des choses dans ce genre tres facilement) mais lorsque je passe à la pratique j'ai l'impression qu'il faudrait faire appel à des constructeurs/destructeurs....
    ==> pour resumer: je ne suis pas certains que programmer comme ceci soit la meilleurs solution

    2°) Mon second probleme est que j'ai des difficultés à mélanger toutes ces nouvelles notions: STRING, VECTOR, LECTURE DE FICHIER et à cela les pointeurs

  3. #3
    Membre expérimenté
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Par défaut
    Plusieurs questions :
    • Pourquoi la variable dataBase est-elle globale ?

    • Pourquoi passes tu l'adresse d'un pointeur à une fonction qui demande un pointeur ?

    • As tu remarqué que tu déclare un pointeur sur un entier (dataBase et que tu veut y stoocker un string ?


    • A ma connaissance la classe string ne possède pas de méthode open

    • Tu as réussi à compiler ton code

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    merci beaucoup d'avoir pris le temps de répondre,
    je ne suis pas arrivé à compiler, je vous ai présenté ici le programme presque complet que je voudrais pour vous donner une idée mais en fait j'ai essayer des choses plus simples et je ne suis pas arrivé non plus à compiler.

    Citation Envoyé par andnicam Voir le message
    Pourquoi la variable dataBase est-elle globale ?[/LIST]

    c'est surement une erreur de ma part
    : en fait dans les tuto que j'ai vu on fait comme cela pour allouer de la memoire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        int *variable = NULL;
        variable = new int; // Allocation de mémoire
        delete variable; // Libération de mémoire
        return 0;
    }
    Donc j'ai mis database dans le main pour prendre la meme structure que ci dessus

    Citation Envoyé par andnicam Voir le message
    Pourquoi passe tu l'adresse d'un pointeur à une fonction qui demande un pointeur ?
    c'est une erreur de ma part, j'ai confondu voila ce qui est correct à mon avis:
    Citation Envoyé par andnicam Voir le message
    As tu remarqué que tu déclare un pointeur sur un entier (dataBase et que tu veut y stoocker un string ?
    exact c'est encore une erreur , en fait dans les tuto que j'ai fait les pointeurs etaient toujours des int ou double donc j'ai fais ceci sans me rendre compte, ceci est plus correct je pense ?:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string *dataBase = NULL;
    Citation Envoyé par andnicam Voir le message
    Pourquoi déclares tu cette variable de manière globale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector <string> matrix;
    Pour ce point je ne sais pas quoi repondre car je ne sais pas trop comment je dois structurer mon programme et je n'ai pas l'habitude d'utiliser vector, j'ai fais un peut par defaut en essayant de recopier des morceaux de code d'un tuto/faq
    (attention j'ai apporté une modif sur ce point par rapport à mon premier post)

    Citation Envoyé par andnicam Voir le message
    A ma connaissance la classe string ne possède pas de méthode open
    ah bon? comment faire donc pour lire mon fichier au travers de cette fonction input?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Par défaut
    Pour ouvrir un fichier il faut utiliser les classes istream ou ifstream (Ouverture fichier).
    Je te conseille de jeter un oeil sur ce lien Reference c++, pour les fonctionnalités de références.

    Exemple de code pour ouvrir un fichier texte en lecture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <iostream>
    #include <fstream>
    [...]
    filebuf fb;
    fb.open ("dataBase.txt",ios::in);
    istream is(&fb);     // Ceci est ton flux sur le fichier c'est à partir de lui que tu pourras faire des manipulations
    Pour lire les lignes de texte dans le fichier je te conseil la fonction getline qui renvoie un string

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string ligne;
    getline( is,ligne );
    Ainsi le contenu de la ligne du fichier est stockée dans l'objet de type string. Aprés la classe string de la STL te permet tout un tas de manipulation (classe string

    Concernant le vecteur d'objet Matrix (matrix) tout dépend de ce que tu veux en faire. La fonction imput pourrait par exemple te renvoyer un pointeur sur le vecteur, ou bien tu peux le passer en référence à la fonction input qui le met à jour.
    Là il faut en dire un peu plus sur ce que tu veux faire exactement.

  6. #6
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonjour,

    Pour commencer, on n'inclut dans un fichier source que ce qui est nécessaire.
    Ça évite de créer des dépendances inutiles, et tout ce que ça implique…
    Donc quand tu veux utiliser la directive « #include », demande-toi si tu as besoin d'éléments déclarés dans le fichier à inclure dans le fichier source en cours d'écriture.
    Tu peux aussi te demander si le fichier que tu veux inclure n'est pas déjà inclus dans un des fichiers inclus.
    Tu devrais d'ailleurs le faire, lorsque tu écris un fichier d'implémentation (.cpp), pour les fichiers inclus dans le fichier d'en-tête (.h).

    Un petit exemple vaut bien une longue explication…
    toto.h
    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
    #ifndef TOTO_H
    #define TOTO_H
     
     
    #include <iostream>
    // Pas nécessaire, donc inutile, donc on supprime !
     
    #include <string>
    // Indispensable, donc on garde
     
     
    void titi(const std::string&);
     
     
    #endif // TOTO_H
    toto.cpp
    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
    #include <iostream>
    // Indispensable, donc on garde
     
    #include <string>
    // Indispensable, mais inclus dans le fichier « toto.h », donc on supprime !
     
    #include "toto.h"
    // Indispensable, donc on garde
     
     
    using namespace std;
     
    void titi(const string& s)
    {
        cout << "Le paramètre de la fonction est : " << s << endl;
    }

    Ensuite, on ne fait d'allocation dynamique que lorsque l'on en a vraiment besoin.
    L'allocation statique est beaucoup plus fiable et sûre, moins sujette aux erreurs, en particulier les fuites de mémoire.
    Pour ta variable dataBase du main, tu sais précisément de quelle manière et à quel moment elle va être créée, et tu n'en as pas besoin hors du scope de la fonction « main » ; alors une allocation statique est requise.
    Les deux instructions suivantes sont équivalentes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string dataBase = "dataBase.txt";
    string dataBase("dataBase.txt");

    Maintenant, deux petites remarques.
    Lorsque l'on veut accéder à l'élément x du pointeur ptr, tu as compris qu'il faut écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*ptr).x // Avec les parenthèses, c'est plus clair
    Mais il existe un raccourci d'écriture très pratique, et non ambigu :
    Il fonctionne aussi bien avec les attributs membres qu'avec les fonctions membres.

    Puisqu'il faut de toute façon passer le nom du fichier à ouvrir à la fonction « input() », il n'y a pas de raison de passer un pointeur.
    Donc une signature plus correcte serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void input(std::string dataBase);
    Sauf que dans ce cas, la chaîne de caractères va être dupliquée, ce qui n'est guère souhaitable.
    Pour pallier ce problème, le C++ introduit ce qu'on appelle les « références » (F.A.Q.) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void input(std::string& dataBase);
    Cette fois, la chaîne ne sera pas dupliquée.
    Mais elle n'est pas censée être modifiée dans la fonction, alors on rajoute le mot-clé « const » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void input(const std::string& dataBase);

    L'utilisation des références est un casse-tête pour les débutants (pas que pour eux, d'ailleurs…).
    Alors si tu n'es pas à l'aise, tu peux continuer à utiliser des pointeurs dans un premier temps ; mais il faut que tu saches que ça existe, et comment ça s'utilise.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void input(const std::string *dataBase);

    Concernant la lecture d'un fichier, il va falloir te documenter sur les classes de type « fstream », et plus généralement sur les flux d'entrée/sortie (input/output streams).
    www.cppreference.com
    www.cplusplus.com
    Je vois que tu as déjà inclus le fichier d'en-tête, mais tu n'es pas allé jusqu'au bout.

    Si tu as d'autres questions, n'hésite pas.

  7. #7
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par andnicam Voir le message
    Exemple de code pour ouvrir un fichier texte en lecture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <iostream>
    #include <fstream>
    [...]
    filebuf fb;
    fb.open ("dataBase.txt",ios::in);
    istream is(&fb);     // Ceci est ton flux sur le fichier c'est à partir de lui que tu pourras faire des manipulations
    Euh… quel est l'intérêt de créer un « std::filebuf » si c'est pour l'utiliser via un « std::istream » ?
    C'est exactement comme créer directement un « std::{i,o}fstream », sauf que l'on a un objet de plus à gérer…

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    c'est tres gentil d'avoir repondu, je vais regarder cela car il y a beaucoup de choses que je dois comprendre et je te tiens au courant.

    merci encore

    A+

    ps: j'avais fait une allocation dynamique car je ne sais pas la taille du fichier texte et cette taille peut etre variable selon les données que rentre l'utilisateur avant de lancer le programme mais c'est vrai qu'une fois le programme lancé la taille ne bouge plus

  9. #9
    Membre expérimenté
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227

  10. #10
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par 21did21 Voir le message
    ps: j'avais fait une allocation dynamique car je ne sais pas la taille du fichier texte et cette taille peut etre variable selon les données que rentre l'utilisateur avant de lancer le programme mais c'est vrai qu'une fois le programme lancé la taille ne bouge plus
    Toutes les instances d'un type donné font exactement la même taille.
    Tu peux essayer d'appeler l'opérateur sizeof() sur, par exemple, un std::string vide et un std::string d'une centaine de caractères, et tu verras.
    Je ne vais pas entrer dans les détails, et de toute façon je ne saurais pas l'expliquer clairement, mais c'est comme ça.

    C'était légitime de penser que la taille des données pourrait changer selon le fichier lu, mais finalement pas justifié.
    Les structures complexes, comme les chaînes de caractères, les conteneurs ou les flux utilisent des structures internes pour stocker les données ; ce qui ne modifie pas la taille de l'objet réellement manipulé par le programmeur.

  11. #11
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par andnicam Voir le message
    dans ce cas le filebuf est transparent
    C'est exactement ce que je voulais pointer du doigt.

  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
    Salut,

    Hé bien, je ne veux pas enfoncer le clou, mais il y a effectivement place pour le progres
    1. tu ne dois utiliser les pointeurs que si tu y es réellement obligé... Tu as bien meilleur temps de travailler avec de références, que tu peux déclarer constantes si tu ne souhaite pas que la fonction appelée les modifie
    2. (découle directement du (1) ) L'allocation dynamique de la mémoire ne doit être utilisée que lorsque l'on n'a vraiment pas le choix, entre autres, lorsque l'on souhaite assurer le polymorphisme, or, ici, il n'en n'est pas question
    3. Tu devrais utiliser les possibilités offertes par le standard pour lire et interpréter ton fichier... Cela serait bien plus facile
    Un petit exemple qui mettrait en pratique ce que je viens de dire (ou d'écrire en fait ) "vite fait" :
    Je me trompe peut être, mais j'identifie trois types de données bien distinctes (désolé, mais mes cours de chimie remontent "au moyen age" ):
    • Matrixe : elle est composée d'un nom, sous la forme d'une chaine de caractères, d'un réel représentant le paramètre de latence () et d'un deuxième réel représentant le poid volumique.
    • Precipitate: il est également composé d'un nom, sous la forme d'une chaine de caractères, d'un réel représentant le paramètre de latence () et... il manquerait pas une valeur pour le poids volumique
    • Element: composé d'un nom sous la forme d'une chaine de caractères, d'un entier "stoechiometrique" (un terme qui ne me dit rien ) et d'un deuxième entier représentant le coefficient (de quoi j'espère que tu le sais )
    De prime abord, je dirais que les matrix et les precipitates peuvent partager une structure de donnée identique, mais bon, il faudrait que tu me confirme que l'on peut effectivement gérer l'un comme si c'était l'autre (dans le doute, je considérerai que c'est le cas, pour la facilité ), L'élément, quant à lui, doit utiliser un structure de donnée qui lui est propre

    Nous aurions donc deux structures bien distinctes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* la structure de données pour les matrix et les precipitates */
    struct MatrixAndPrecipitate
    {
        std::string nom;
        double latence;
        double poidsVolumique;
    };
    /* la structure de données pour les éléments */
    struct Element
    {
        std::string nom;
        int stoechiometrique;
        int coeff;
    };
    Comme je n'ai pas trop regardé ton code, et que je ne sais donc pas selon quels critères tu souhaites effectuer ton tri, je vais, par facilité, créer ce que l'on appelle des "foncteurs" (des "fonctions objets" ) qui nous permettront de déterminer, pour chacun des critères de tri que l'on pourrait envisager, si un élément est "plus petit" que l'autre:
    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
    /* celui-ci servira pour les deux et nous permet un tri par nom */
    struct lessByName
    {
        bool operator()(MatrixAndPrecipitate const & first, MatrixAndPrecipitate
                        const & second)
        {
            return first.nom<second.nom;
        }
        bool operator()(Element const & first, Element const & second)
        {
            return first.nom<second.nom;
        }
    };
    /* celui-ci sert pour les matrix et les précipités, et nous permet un tri
     * par latence
     */
    struct lessByLatice
    {
        bool operator()(MatrixAndPrecipitate const & first, MatrixAndPrecipitate
                        const & second)
        {
            return first.latence<second.latence;
        }
    };
     
    /* celui-ci sert pour les matrix et les précipités, et nous permet un tri
     * par poids volumique
     */
    struct lessByPoidsVolumique
    {
        bool operator()(MatrixAndPrecipitate const & first, MatrixAndPrecipitate
                        const & second)
        {
            return first.poidsVolumique<second.poidsVolumique;
        }
    };
     
    /* celui-ci sert pour les éléments, et nous permet un tri
     * par "stoechiometrique"
     */
    struct lessByCoeff
    {
        bool operator()(Element const & first, Elementconst & second)
        {
            return first.stoechiometrique<second.stoechiometrique;
        }
    };
    /* Enfin, celui-ci sert pour les éléments, et nous permet un tri
     * par coefficient
     */
    struct lessByStoechiometrique
    {
        bool operator()(Element const & first, Elementconst & second)
        {
            return first.coeff<second.coeff;
        }
    };
    Je les mets bien de côté, je t'expliquerai en temps utiles comment les utiliser

    Car, avant de vouloir les utiliser, il me semble intéressant de pouvoir récupérer les informations au départ du fichier dans lequel elles se trouvent

    Il y a deux possibilités pour permettre à l'utilisateur de fournir le nom du fichier qui doit être géré:
    • Soit, l'utilisateur introduit un (ou plusieurs) nom(s) de fichiers en ligne de commande (sous la forme de monapp fichierTexte.txt fichierTextetxt), mais je considérerai (toujours par facilité) qu'il introduit un seul nom de fichier à la fois
    • Soit l'utilisateur lance l'application, qui devra alors veiller à lui demander le(s) nom(s) de fichier(s) qu'il souhaite utiliser. Par facilité, je considérerai que l'utilisateur ne veut utiliser qu'une seul fichier
    Comme il est "relativement" facile de prendre les deux cas en compte, voici comment se présenterait la fonction principale:
    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
    int main(int argc, char *argv[])
    {
        /* nous prévoyons une chaine de caractères pour représenter le nom
         * du fichier
         */
        std::string filename;
        /* si l'utilisateur a fourni un nom de fichier en ligne de commande, on 
         * l'utilise
         */
        if(arc> 1)
            filename=argv[1];
        /* sinon, nous demandons à l'utilisateur d'introduire le nom du fichier */
        else
        {
            std::cout<<"Veuillez introduire le nom du fichier a utiliser :";
            std::cin>>filename; //(*)
        }
        /* nous préparons les tableaux pour les matrixe et les précipités, et pour 
         * les éléments
         */
        std::vector<MatrixAndPrecipitate> tabMatPre;
        std::vector<Element> tabElem;
        /* Et nous transmettons tout cela à la fonction qui se chargera de lire
         * le fichier
         */
        readfile(filename,tabMatPre,tabElem); // voir plus bas
        /* il ne restera plus qu'à gérer ces informations "à ta bonne convenance"
         */
        return 0;
    }
    (*) j'ai cédé à la flegme, et je considère (pour une fois) que l'utilisateur n'est pas un imbécile distrait, et qu'il introduira donc un nom de fichier valide ... Il aurait été pas mal de gérer les introductions erronées La fonction de lecteur se présenterait sous une forme 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
    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
    71
    72
    73
    74
    75
    76
    void readFile(std::string const & filename, 
                 std::vector<MatrixAndPrecipitate> & tabMatPre,
                 std::vector<Element> & tabElem)
    {
        /* ouvrons le fichier dont le nom a été donné */
        std::ifstream ifs(filename.c_str());//(*)(**)
        /* s'il a été ouvert, on peut travailler :D */
        if(ifs)
        {
            /* nous allons récupérer le contenu de fichier ligne par ligne...
             * nous avons besoin d'une chaine de caractères pour ce faire :D
             */
            std::string temp;
            /* tant que nous arrivons à lire quelque chose */
            while(std::getline(ifs,temp)
            {
                /* une ligne qui commence par '#' est un commentaire, nous ne
                 * gérons donc que les lignes... qui ne commencent pas par '#' :D
                 */
                if(temp[0]!='#')
                {
                    /* le plus facile pour convertir une chaine de caractère
                     * en n'importe quoi consiste à utiliser le flux de conversion
                     * "stringstream"
                     */
                     std::stringstream ss;
                     /* que nous remplissons avec la chaine que l'on vient de lire
                      */
                     ss<<temp;
                     /* dont nous extrayons directement le premier terme */
                     ss>>temp;
                     /* Nous nous attendons à ce qu'il vaille matrix  ou
                      * precipitate 
                      */
                     if(temp=="matrix" || temp=="precipitate")
                     {
                         /* auquel cas, nous créons un objet de type 
                          * MatrixAndPrecipitate
                          */
                           MatrixAndPrecipitate item;
                           /* auquel nous donnons les valeurs correctes
                            */
                           if(!ss>>item.nom>>item.latence>>item.poidsVolumique)
                           {
                               /* si cela échoue, nous lancons une exception...
                                * car le format du fichier n'est pas bon
                                */
                                throw BadFileFormat(); // à définir toi-même :D (***)
                                                        // (****)
                           }
                           /* et que nous plaçons dans le tableau */
                           tabMatPre.push_back(item);
                     }
                     /* ou alors, c'est un élément */
                     else if(temp=="element")
                     {
                        /* pour lequel nous utilisons la même logique, en l'adaptant
                         * au type "Element"
                         */
                           Element item;
                           if(!ss>>item.nom>>item.stoechiometrique
                                 >>item.coeff)
                           {
                                throw BadFileFormat();
                           }
                           tabElem.push_back(item);
                     }
                     /* Et si ce n'est rien de tout cela, nous lançons une exception
                      * car on ne sait pas quoi faire
                      */
                     else
                         throw BadItemType(); // à définir toi-même (***)(****)
                }
            }
        }
    }
    NOTA:
    • (*)La création d'un flux de fichier (en entrée comme c'est le cas ici ou en sortie) ouvre automatiquement le fichier dont le nom est donné en paramètre... nous ne devons donc pas nous inquiéter d'invoquer la fonction open
    • (**)Le flux de type ifstream est automatiquement ouvert en lecture et en mode "texte" si on ne précise pas le contraire... Il est donc inutile de lui passer le second argument, car c'est justement ce que l'on souhaite
    • (***)Les exceptions sont à définir toi-même, mais ce peut parfaitement être de simples structures vides
    • (****)Le fait que nous lancions une exception sans avoir prévu de la récupéer (afin de la gérer) dans la fonction principale aura pour conséquence de faire "planter" le programme... Cependant, comme cela n'arrive que si nous n'avons pas été en mesure de récupérer correctement les informations du fichier, nous pouvons considérer qu'il s'agit d'une issue cohérente de l'application, vu que cela met en avant un problème quant au contenu du fichier que l'on a essayé de lire


    Il ne nous reste plus qu'à voir comment utiliser les foncteurs que j'ai préparé là tantôt et tenus bien "au chaud"

    Le standard fournit un tas d'algorithm sympa dans un fichier d'en-tête nommé (qui l'eut cru ) <algorithm>.

    Parmi les algorithm fournis, on trouve std::sort, qui prend trois argument: un itérateur sur le premier élément à trier, un itérateur sur "ce qui suit" le dernier élément à trier et un foncteur.

    Ce qui est chouette, c'est que la classe vector (comme toutes les autres collections, d'ailleurs) présente, justement, des fonctions qui permettent d'obtenir ces deux itérateurs: begin() pour le premier, end() pour le second.

    Le fait d'avoir défini les foncteurs que je présentais plus haut nous permet de faire en sorte de trier nos tableaux simplement en invoquant cette fonction sort:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /* si on veut trier les matrix par nom: */
    std::sort(tabMatPre.begin(),tabMatPre.end(),lessByName());
    /* si on veut trier les élément par nom */
    std::sort(tabElem.begin(),tabElem.end(),lessByName());
    /* si on veut trier les élément par leur coefficient */
    std::sort(tabElem.begin(),tabElem.end(),lessByCoeff());
    /* et ainsi de suite */
    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

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    merci beaucoup tous d'avoir pris le temps de répondre (et pour vos longue réponses) mais je pense que je vais commencer petit à petit par des choses simples car je me rends compte que je ne maitrise pas grand chose.

    Dans un premier temps j'ai commencé par m'interesser à ce fichier texte (data.txt):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    # premier type de données
    matrix ferrite 2.85 1e-30
    matrix aluminium 1.85 1.2e-30
     
    # deuxieme type de données
    precipitate VC 4.1
    precipitate Mg2Si 4
    precipitate Mg5Si6 4.7
    Je vais essayer juste de lire mot pas mot le fichier et classer selon si le mot clef est matrix ou precipitate

    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
    #include <iostream>
    #include <fstream>
    using namespace std;
    int main()
    {
        string mon_fichier = "data.txt";  // je stocke dans la chaîne mon_fichier le nom du fichier à ouvrir
        ifstream dataBase(mon_fichier.c_str(), ios::in);
        if(dataBase)  // si l'ouverture a réussi
        {
            while (!dataBase.eof()) //temps que l'on a pas tout lu
            {
                  if (!dataBase.eof())
                  {
                      string command, dump;
                      dataBase >> command;
     
                      if (command=="#")
                      {
                          getline(dataBase,dump);
                          cout << dump << endl;
                      }
                      else if (command=="matrix")
                      {
                          string MatrixName;
                          double LatticeParameter_M, AtomicVolume_M;
                          cout << "matrix command invoqued"  << endl;
                          dataBase >> command;
                          MatrixName = command;
                          dataBase >> command;
                          LatticeParameter_M = command;
                          dataBase >> command;
                          AtomicVolume_M = command;
                          cout << MatrixName << LatticeParameter_M << AtomicVolume_M << endl;
                       }
                       else if (command=="precipitate")
                       {
                          string PrecipitateName;
                          double LatticeParameter_P;
                          cout << "precipitate command invoqued"  << endl;
                          dataBase >> command;
                          PrecipitateName = command;
                          dataBase >> command;
                          LatticeParameter_P = command;
                          cout << PrecipitateName << LatticeParameter_P << endl;
                       }
                       else
                       {
                       }
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else  // sinon
            {
                 cout << "Impossible d'ouvrir le fichier !" << endl;
            }
            dataBase.close();  // on ferme le dataBase
            return 0;
    }


    Ce programme "essaie" de mettre les parametre de matrice et precipitate dans des variables.

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    le probleme (je crois) est que la variable commande est un string et que moi il me faut des doubles pour certains parametres

    voici l'erreur affichée

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    Je pense que je vais fermer ce poste car c'est "le bordel",
    je vais reprendre petit à petit mon probleme et je posserai des questions sur des points precis je pense que ca sera plus clair pour tous (y compris pour moi)

    merci beacoup tous de votre participation

    A+

  16. #16
    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
    Tu devrais cependant prendre le temps de relire mon intervention à ton aise...

    Et surtout les commentaires, que j'ai pris soin de placer dans tout le code

    Tout ce que je dis te viendra bien à point, même si tu décide par la suite d'avancer "à petits pas"
    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

  17. #17
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Tu devrais cependant prendre le temps de relire mon intervention à ton aise...
    Et surtout les commentaires, que j'ai pris soin de placer dans tout le code
    Tout ce que je dis te viendra bien à point, même si tu décide par la suite d'avancer "à petits pas"
    oui koala je vais bien relire tous cela attentivement ne t'inquiete pas mais en parallele je vais essayer d'avancer à petit pas (car je me rend compte qu'il me manque pas mal de base pour comprendre ton intervention)

    merci en tout cas pour ton aide, c'est tres gentil

  18. #18
    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 21did21 Voir le message
    oui koala je vais bien relire tous cela attentivement ne t'inquiete pas mais en parallele je vais essayer d'avancer à petit pas (car je me rend compte qu'il me manque pas mal de base pour comprendre ton intervention)
    N'hésite pas à poser des questions sur mon intervention s'il te manque un concept ou un autre...

    J'ai essayé de mettre des commentaires utiles et opportuns, mais il est vrai qu'ils se basent, malgré tout, sur une connaissance minimale du langage et de la programmation

    Et je suis tout à fait prêt (comme d'autres sans doute) à expliciter tout point qui semblerait obscure
    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

  19. #19
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    Citation Envoyé par koala01 Voir le message
    N'hésite pas à poser des questions sur mon intervention s'il te manque un concept ou un autre...
    J'ai essayé de mettre des commentaires utiles et opportuns, mais il est vrai qu'ils se basent, malgré tout, sur une connaissance minimale du langage et de la programmation
    Et je suis tout à fait prêt (comme d'autres sans doute) à expliciter tout point qui semblerait obscure
    c'est tres gentil "quel accueil" (je n'ai pas eu le meme sur d'autres forum)

  20. #20
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Une petite précision sur la fonction membre « std::istream::eof() » en passant…
    Un flux ne détecte qu'il est arrivé à la fin (du fichier) que lorsqu'il essaye de lire des données alors qu'il n'y en a plus.

    Autrement dit, si tu ouvres un fichier vide, ou après avoir lu la dernière ligne d'un fichier, eof() retournera false.
    Ce n'est qu'après la prochaine tentative de lecture qu'elle retournera true.

    En général, lorsque l'on se contente de lire un fichier ligne par ligne, on n'utilise pas cette fonction : on préfère tester la valeur de retour de la fonction « std::getline() ».
    Elle retourne une référence sur le flux utilisé, mais il existe une conversion implicite en booléen :
    • true : la lecture s'est correctement déroulée ;
    • false : une erreur est survenue (souvent, la fin du flux a été atteinte).


    Bonne continuation !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 20
    Dernier message: 01/11/2007, 13h52
  2. Comment lire un fichier et extraire des données
    Par salut93 dans le forum MATLAB
    Réponses: 14
    Dernier message: 12/06/2007, 11h27
  3. mettre fichiers avec déjà des données dans répertoire
    Par petitange_lili dans le forum Langage
    Réponses: 1
    Dernier message: 22/03/2007, 08h23
  4. Réponses: 1
    Dernier message: 23/12/2006, 23h39
  5. fichier CSV modification des données.
    Par suya95 dans le forum Excel
    Réponses: 8
    Dernier message: 26/07/2006, 12h22

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