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

SL & STL C++ Discussion :

mettre les termes d'un string dans une struct


Sujet :

SL & STL C++

  1. #1
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut mettre les termes d'un string dans une struct
    encore mon probleme de structure

    je dois recuperer des donnees contenue dans des string se trouvant dans un ou plusieur fichiers
    un string contient nom;prenom;adresse;....
    je me dis que je vais creer une structure pour les mettre dedans et ayant plusieurs string a traiter, j'ai créé un vecteurde ma structure.
    mais je ne vois pas comment inserer chaque terme a l'interieur.
    ci-dessous mon code


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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
    struct A
    {
    	string nom;
    	string prenom;
    	string rue;
    	string num_rue;
    	string ville;
    	string pays;
     
    	struct compte
    	{
    		string tab_compte[200];
    	};
    };
     
    vector<A> vec_A;
     
    int main(int argc, char *argv[])
    {
    	//recuperation noms de fichier et affichage
    	cout << "Liste des fichiers" << endl;
     
    	for (int i = 1; i < argc; i++)
    	{
    		cout << "Fichier " << i << " : " << argv[i] << endl;
    	}
     
    	for (i=1; i < argc ; i++)		//on examine tout les fichiers entres en ligne de commande
    	{
    		//ouverture fichier
    		ifstream fichier(argv[i]);
    		//controle existence du fichier
    		if (!fichier) 
    		{
    			cerr << "Impossible d'ouvrir le fichier " << argv[i] << endl;
    			exit(EXIT_FAILURE);
    		}
     
    		string s1,s2;
     
    		while (!fichier.eof())		//on boucle tant qu'on est pas a la fin du fichier
    		{
    			//recupere la ligne
    			getline(fichier,s1);
    			int tmp = 0;
    			for (size_t i = 0; i < s1.length(); i++)
    			{
    				if (s1[i] == ';')	//si onrencontre le separateur ;
    				{
    					s2 = s1.substr(tmp,(i-tmp));	//on copie le terme dans s2
    					tmp = i+1;
    					cout <<  s2 << " ";
    				}
    			}
    			cout << endl;
    		}
    		fichier.close();
    	}
     
     
     
    	return 0;
    }
    j'arrive a extraire chaque terme mais comment l'inserer a la bonne place dans la structure??

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Si ta ligne est toujours composée du même nombre de champs distinct, il ne faut pas les extraire dans une boucle, il te faudra les récupérer un à un et les mettre ensuite dans la donnée membre de A correspondante.

    Autre solution : stocker toutes tes données dans un tableau, et faire a.Champ[i] = s2 à chaque tour de boucle.

    Encore une autre : utiliser un std::map<string, string> pour stocker tes membres, et un tableau contenant les nom de ces membres.
    Genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A
    {
       map<string, string> Membres;
    };
     
    static const char* Champs[] = {"nom", "prenom", "rue", ...}
     
    for (...)
    {
       a.Membres[Champs[i]] = s2;
    }
    Astuce : tu peux utiliser getline avec comme 3eme paramètre ';' pour récupérer tes sous-chaines, au lieu de find + substr.

  3. #3
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut
    j'ai du faire une boucle car le nombre de champs peut varier
    si les infos concernant la personne sont toujours pareils, j'ai des numero de compte a la fin avec un solde, et je peut en avoir un ou plusieurs.
    je me base donc sur \n pour la fin de ligne

    j'ai effectivement penser a mettre chaque terme dans un tableau (en fait un vecteur car je ne connais pas la taille a l'avance) mais je seche sur la facon de gerer le string suivant
    comment le faire avancer sur le membre suivant (suis pas sur d'etre clair la)

  4. #4
    En attente de confirmation mail
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    150
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 150
    Points : 180
    Points
    180
    Par défaut
    mais en fait ta string peut etre composée de x parametres dont le maximum est connu du genre

    nom;prenom;adresse

    mais aussi, parfois:

    nom;prenom;adress;compte

    Est-ce que tu peux influer sur la generation des string ?

    du genre quand un parametre est sauté metre ;

    nom;;;compte ???

    Dans ce cas le parsing de ta string est simple...

  5. #5
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 749
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 749
    Points : 10 666
    Points
    10 666
    Billets dans le blog
    3
    Par défaut
    Quelques remarques:
    - pourquoi n'utilises-tu pas un vector pour tab_compte ?
    - le test
    n'est pas suffisant : la lecture peut échouer pour d'autres rainsons que la fin de fichier. remplace plutot cette ligne et la suivante par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ( getline(fichier,s1) )
    voir la FAQ pour les explications
    - il ne faut pas utiliser exit() dans les programmes C++. Fait un simple return.

    Pour ton problème tu peux coder une fonction qui crée un objet A à partir d'une chaine et d'un position de début dedans. Du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    size_t ExtractA( const std::string & S, size_t pos, A & Result )
    {
        // parcourir S à partir de pos
        // lire tous les champs en comptant le nombre de carcatères lus
        // remplir Result au fur et à mesure
        // renvoyer 0 si on est en fin de chaine et que tout n'est pas initialisé
        // sinon renvoyer le nombre de caractères traités
    }
    Ce peut être une fonction membre statique de struct A. Tu pourrais l'utiliser ainsi :
    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
     
    while ( getline(fichier,s) )
    {
        size_t i = 0;
        A a;
        while ( i < s.length() )
        {
            size_t read = ExtractA( s, i, a );
            if ( read == 0 )
            {
                // erreur
            }
            vec_A.push_back( a );
            i += read;
        }
    }

  6. #6
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut
    je recupere les string dans des fichiers txt
    j'ai ma liste de champs et selon le string compte1, compte2, ou plus encore, mais pas forcement.
    donc seul la fin du string change et je ne peut influer dessus.

  7. #7
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 749
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 749
    Points : 10 666
    Points
    10 666
    Billets dans le blog
    3
    Par défaut
    En fait comme cela ressemble à de la sérialisation, je pense que ce serait le bon endroit de mettre une fonction FromString et ToString dans ta classe A. Si tu modifies ta classes tu corriges le code de ces fonctions et tout le reste du code reste inchangé et marche avec la nouvelle classe.

  8. #8
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    un moyen serait de créer un tableau de string, indicé par un enum.
    L'enum te permets de dimenssionner ton tableau, d'incrémenter l'indice pour ta boucle, et d'accéder facilement à tes champs :
    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
     
    // déclaration 
    enum EnIndice
    {
       Nom,
       Prenom,
       Adresse, 
     
       EnIndiceMax
    };
    std::string Personne[EnIndiceMax];
     
    // utilisation
    Personne[Nom] = UnNomLu;
    ....
    for (int i=0; i<EnIndiceMax; i++)
    {
       std::cout << Personne[i] << std::endl;
    }
    c'est une idée, par forcément LA solution.
    Je crois qu'il y aurait des trucs à faire avec un std::map.

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Si j'ai bien compris, tu cherche à faire ça, non ?
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #include <vector>    // std::vector<>
    #include <string>    // std::string
    #include <sstream>   // std::istringstream
    #include <algorithm> // std::copy
    #include <iterator>  // std::ostream_iterator
    #include <iostream>  
     
    using namespace std;
     
    struct A
    {
        string nom;
        string prenom;
        string rue;
        string num_rue;
        string ville;
        string pays;
     
        vector <string> tab_comptes;
     
        void swap(A & other)
        {
            nom.swap(other.nom);
            prenom.swap(other.prenom);
            rue.swap(other.rue);
            num_rue.swap(other.num_rue);
            ville.swap(other.ville);
            pays.swap(other.pays);
            tab_comptes.swap(other.tab_comptes);
        }
    }; 
     
    std::ostream & operator<<(std::ostream & os, const A & v)
    {
        os << v.nom << " " << v.prenom
            << "  habite au " << v.num_rue << ", " << v.rue
            << " " << v.ville << "(" << v.pays << ") --- "; 
        copy(v.tab_comptes.begin(),v.tab_comptes.end(),
                ostream_iterator<string>(os, ", "));
        return os;
    }
     
    istream & operator>>(istream & is, A & a)
    {
        string ligne;
        if (getline(is,ligne)) {
            istringstream iss(ligne);
            A tmp;
            if (getline(iss,tmp.nom,';') && getline(iss,tmp.prenom,';')
                     && getline(iss,tmp.rue,';') && getline(iss,tmp.num_rue,';')
                     && getline(iss,tmp.ville,';') && getline(iss,tmp.pays,';'))
            {
                string cpt;
                while (getline(iss, cpt, ';')) {
                    tmp.tab_comptes.push_back(cpt);
                }
                // éventuellement vérifier que les numéros de compte sont OK
                // et qu'il y a des comptes.
                a.swap(tmp);
            } else {
                std::cerr << "ERREUR: Entrée incorrecte: " << ligne << "\n";
                is.setstate(std::ios_base::failbit);
            }
        }
        return is;
    }
     
     
    void test(string const & fic)
    {
        cout << fic << "\n";
        istringstream f(fic);
     
        A a;
        while (f >> a)
            std::cout << "---> " << a << "\n";
        if (!f.eof() && f.fail()) 
            std::cout << "Erreur!\n";
     
        cout << "\n------\n";
    }
     
    int main (int argc, char **argv)
    {
        test("toto;titi;avenue truc;15;tlse;fr;1;2;42"
                "\ntata;tutu;rue chose;42;paris;fr;12;15;16");
        test("toto;titi;avenue truc;15;tlse;fr;1;2;42"
                "\ntata;tutu;rue chose;42;paris;fr;12;15;16\n");
        test("toto;titi;avenue truc;15;tlse;fr;1;2;42;5;6;8;9");
        test("toto;titi;avenue truc;15;tlse;fr;");
        test("toto;titi;avenue truc;15;tlse;fr");
        test("toto;titi;avenue truc;15;tlse;");
     
        std::cout << std::endl;
     
        return 0;
    }
    (on peut encore simplifier en sortant boost)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    ça sert à quoi le A::swap() ?
    pourquoi ne pas utiliser le constructeur de recopie par défaut ?

  11. #11
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 749
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 749
    Points : 10 666
    Points
    10 666
    Billets dans le blog
    3
    Par défaut
    Parce que ça fait une recopie
    swap ça échange le contenu, sans le copier.

  12. #12
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    dans ce cas-là, deux std::string ont le même espace mémoire alors ?

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    ??
    Les buffers internes sont échangés.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  14. #14
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut

  15. #15
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut
    bon bin on va etudier tout ca hein

    ca me fait du boulot pour ce soir

  16. #16
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut
    d'abord, merci pour vos reponses
    j'ai pu comprendre certaines choses et avancer ds mon code et aussi le rendre un peu plus propre

    petite question toutefois concernant ton code Luc,
    ca sert bien a recreer un flux a partir d'un string ?

    a la compilation, j'ai une liste de warning qui apparaissent
    • warning C4786: 'std::reverse_iterator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,std::basic_string<char,std::char_traits<char>,std::allocator<char>
      >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,int>' : identifier was truncated to '255' characters in the debug information

    en fait j'ai 5 fois ce warning, mais je ne comprend pas pourquoi (j'ai eu le meme type de warning en utilisant une list pour stocker mes strings)

    sinon merci pour ton exemple, ca m'a permit de comprendre et de programmer mon traitement (sans plaggia)

  17. #17
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    petite question toutefois concernant ton code Luc,

    ca sert bien a recreer un flux a partir d'un string ?
    C'est ça oui.

    warning C4786: 'std::reverse_iterator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,std::basic_string<char,std::char_traits<char>,std::allocator<char>
    >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,int>' : identifier was truncated to '255' characters in the debug information
    C'est juste que lorsque tu imbriques trop de templates, certains noms de symboles sont trop longs (> 255 caractères), donc il les tronque. Ca n'a absolument aucun effet, le mieux est d'ailleurs de désactiver ce warning à la noix.

  18. #18
    Membre du Club
    Inscrit en
    Février 2003
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 130
    Points : 66
    Points
    66
    Par défaut
    ok merci

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

Discussions similaires

  1. [AC-2003] mettre a jour toutes les valeurs d'un colonne dans une zone de liste
    Par yieiyiei dans le forum VBA Access
    Réponses: 1
    Dernier message: 29/04/2015, 21h41
  2. Mettre les données d'un tableau dans une formulaire
    Par youssefcss dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 28/04/2014, 11h47
  3. Comment mettre les saisies d'un UserForm dans une feuille
    Par Condekilo dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 09/05/2011, 16h13
  4. Réponses: 11
    Dernier message: 06/05/2011, 22h55
  5. Récupérer les valeur d'un énuméré dans une string
    Par Oliv_75 dans le forum SL & STL
    Réponses: 5
    Dernier message: 28/09/2005, 00h55

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