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 :

Algorithmie: manipulation de fichier et strings c++


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut Algorithmie: manipulation de fichier et strings c++
    Bonsoir,

    je m'amuse à apprendre le c++ et j'ai trouvé un problème que je cherche à résoudre:

    On a un fichier contenant des noms, et à côté de ces noms des cours que ces noms suivent.
    Jean: MATHS, SCIENCE, SPORT
    Mathieu: MATHS, SPORT
    Ivan: MATHS, SCIENCE

    Et le but de l'exercice est d'avoir un fichier de sortie sous la forme suivante:
    MATHS: Jean, Mathieu, Ivan
    SCIENCE: Jean, Ivan
    SPORT: Jean, Mathieu

    Je commence d'abord par lire le fichier ligne par ligne (dans un tableau de string avec un string pour chaque ligne).
    Ensuite je traite chaque ligne pour en extraire le nom (partie avant le ':') et les cours qu'il doit suivre. Le tout dans une structure ELEVE(string nom, vector<string> cours, int nbcours).


    Ensuite je créé un tableau contenant tous les ELEVEs et j'extrait les cours que je mets dans un vecteur de string (en supprimant les doubles).
    Et enfin je recréé une structure similaire au type ELEVE, sauf que le nom est désormais celui du cours, et le vector<string> contient les élèves.

    Mais je trouve que cette approche est lourde et longue. Qu'en pensez vous?

  2. #2
    Membre chevronné
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    855
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 855
    Points : 2 177
    Points
    2 177
    Par défaut
    A ta place j'utiliserais plutot une map de vector de string :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    map<string, vector<string> >
    En cle je mettrais le nom de l'eleve puis toutes les matieres qu'il a dans le vector de string. Ensuite le filtre serait plus simple a faire. Cependant ca t'oblige a le faire en 2 fois de cette facon (on enregistre puis on recree une map), tu peux tres bien faire directement ceci (un code sera plus clair qu'une explication) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my_map["MATHS"].push_back("olivier");
    Donc stocker directement les eleves dans la matiere. Je ne pense pas qu'on puisse faire mieux...

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    On peut aussi utiliser dans le même esprit std::multimap.

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    une autre approche est d'avoir un type Matiere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Matiere {
       std::string nom;
       std::set<Eleve*> eleves; // peut être un ref wrapper à la place d'un pointeur
       // ...
    };
    Et la classe Eleve devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct Eleve {
       std::string nom;
       std::set<Matiere*> matieres; // peut être un ref wrapper aussi
       int nbMatieres() const { return matieres.size(); }
       // ...
    };
    Il faut ensuite stocker les Eleves et les Matieres quelque part :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Ecole {
       std::set<Matiere> matieres;
       std::set<Eleve> eleves;
       // ...
    };
    Cette une approche plus solide mais plus lourde à mettre en place.

    Une fois que les données sont rentrées, obtenir

    Jean: MATHS, SCIENCE, SPORT
    Mathieu: MATHS, SPORT
    Ivan: MATHS, SCIENCE

    ou
    MATHS: Jean, Mathieu, Ivan
    SCIENCE: Jean, Ivan
    SPORT: Jean, Mathieu

    n'est qu'une question d'ordre de parcours des données.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut
    Salut!

    Merci beaucoup pour vos réponses, c'est tellement plus simple de cette manière plutôt qu'avec mes anciennes structures.

    J'ai opté pour la solution la plus simple: créér directement une seule map:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    map<string, set<string> > mymap;
    mymap["MATHS"].push_back("olivier");
    J'ai du mal à comprendre comment accéder aux données de map sans itérateur pour pouvoir ensuite afficher le string et son set associé et enfin parcourir son set avec les itérators.

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Salut !

    std::set
    n'a pas de membre appelé push_back, ce serait plutôt insert.

    Si tu utilises C++11, tu peux parcourir tes objets comme dans cet exemple:

    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
    #include <iostream>
    #include <map>
    #include <string>
    #include <set>
    #include <utility>
     
    int main(void) {
      using std::map;
      using std::set;
      using std::string;
      using std::pair;
     
      map<string, set<string>> my_map = {{"MATHS", {"Jean","Mathieu","Ivan"}}, {"SCIENCE", {"Jean","Ivan"}}, {"SPORT", {"Jean","Mathieu"}}};
      for(pair<string const&, set<string> const&> matiere : my_map) {
        std::cout << matiere.first << ": ";
        for(string const& eleve : matiere.second) {
          std::cout << eleve << " ";
        }
        std::cout << std::endl;
      }
     
      return 0;
    }
    Mais rien ne t'empêche d'utiliser un intérateur. Le seul truc qui change avec les itérateurs de map, c'est que le déréférencer pointe vers une paire dont le premier élément est la clé (la matière) et le second la valeur (le set d'élèves). On ne peut pas avoir d'itérateur sur les valeurs seules.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut
    Merci
    Ensuite l'écriture se fait naturellement à la sortie

    Les élèves semblent s'afficher par ordre alphabétique mais cela dépend pour les cours. Pour l'instant je reprend les lignes du fichiers de sortie et je les reclasse ensuite par ordre alphabétique en les mettant dans un vecteur (tri à bulle ).Y a t il un moyen plus simple?

    Je pense que je vais faire ça avec des itérateurs, dans l'ennoncé du problème je ne trouve pas de #include <pair>. Ou sinon il serait plus simple d'utiliser des map<string,vector<string>> ?

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Salut

    pair est inclus par le header utility. Utiliser un itérateur ne t'évitera pas l'usage de pair, même si tu ne le vois pas forcément car tu ne déclare pas directement de variable portant ce type. Utiliser un vector ne change rien non plus dans ce cas.

    map et set sont des collections ordonnées. Dans une map, les clés sont triées par ordre lexicographiques, dans un set, pareil, à part que clé et contenu sont une seule et même chose. Si tu utilises une map pour les matières, elles seront triées. Si tu utilises unordered_map, elles ne se le seront à priori pas, mais tu ne peux avoir aucune garantie sur l'ordre obtenu.

    Si tu tries par ordre lexicographique, tu n'as pas besoin de trier préalablement dans un vector, puisque l'insertion dans la map ou le set effectuera ce tri. Si tu souhaites que les noms des élèves s'affichent dans l'ordre d'insertion de ceux-ci, utilise alors un vector où une list (au risque d'avoir des doublons). Si tu as besoin de trier un vecteur, préfère l'usage de std::sort.

  9. #9
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      map<string, set<string>> my_map = {{"MATHS", {"Jean","Mathieu","Ivan"}}, {"SCIENCE", {"Jean","Ivan"}}, {"SPORT", {"Jean","Mathieu"}}};
      for(pair<string const&, set<string> const&> matiere : my_map) {
    Ce ne serait pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for(pair<string const&, set<string> > const& matiere : my_map)
    voire carrément :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for(auto const& matiere : my_map)

  10. #10
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Ce ne serait pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for(pair<string const&, set<string> > const& matiere : my_map)
    Surtout pas, car tu vas effectuer des copies inutiles des set<string> ! J'ai fait l'expérience de cette erreur pas plus tard qu'hier. Tu peux effectivement rajouter un const& derrière la paire elle-même mais si elle ne contient que des références je pense que ça ne change pas grand chose. Pour auto, je ne sais pas comment il se comporte dans ce cas, à étudier.

  11. #11
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut
    Je viens juste de débuter en programmation, excusez mes questions naives

    Je suis obligé d'avoir le header utility alors même avec des itérateurs?

  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Citation Envoyé par marcelin88 Voir le message
    Je suis obligé d'avoir le header utility alors même avec des itérateurs?
    Non, tu n'en as même pas besoin dans mon exemple en fait, ça compile sans.

  13. #13
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Surtout pas, car tu vas effectuer des copies inutiles des set<string> ! J'ai fait l'expérience de cette erreur pas plus tard qu'hier. Tu peux effectivement rajouter un const& derrière la paire elle-même mais si elle ne contient que des références je pense que ça ne change pas grand chose. Pour auto, je ne sais pas comment il se comporte dans ce cas, à étudier.
    Effectivement, il faut enlever la référence en trop (je n’aurais jamais pensé qu’elle provoquerait une copie, j’aurais plutôt attendu une erreur de compilation même si je vois pourquoi ça passe au final) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(pair<string const&, set<string> > const& matiere : my_map)
    // supprimer le &. map<string, set<string> >::value_type est défini comme pair<string const, set<string> >

  14. #14
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut
    Merci beaucoup tout marche parfaitement

    Je me pose une question: si on veut vérifier qu'il n'y ai pas de professeur en double, et de matières en double dans le fichier d'entrée. J'ai une solution en tête: dans ma fonction qui exploite les lignes, j'insère chaque élève dans un vecteur, et à chaque ligne j'insère chaque cours dans un tableau.
    Je vérifie à chaque ligne qu'il n'y ai pas deux fois le même élément dans un tableau.
    De même à la fin de la fonction pour le professeur.

    Est ce le plus optimal?

  15. #15
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Tu peux utiliser des std::set.

    Ils garantissent l'unicité.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::set<int> s;
    s.insert(5);
    assert(s.size() == 1); // 1 élément
     
    s.insert(5);
    assert(s.size() == 1); // toujours 1 élément, le 5 n'est pas inclus en double
     
    s.insert(4);
    assert(s.size() == 2); // 2 éléments : 4 et 5

  16. #16
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2014
    Messages : 18
    Points : 14
    Points
    14
    Par défaut
    Salut!
    Dernier problème (je l'espère )

    Pour écrire dans le fichier voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      ofstream myfile;
      myfile.open (outFile);
      myfile << stro;
      myfile.close();
    Comment puis je vérifier qu'il n'y a pas eu d'erreur dans l'écriture du fichier et que tout s'est bien passé?

  17. #17
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    746
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 746
    Points : 3 667
    Points
    3 667
    Par défaut
    ios::good() et compagnie.

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

Discussions similaires

  1. Manipulation de fichier (copier, supprimer, déplacer)
    Par Guigui_ dans le forum Général Python
    Réponses: 1
    Dernier message: 21/10/2004, 10h26
  2. Manipulation des fichiers
    Par monsau dans le forum Langage
    Réponses: 7
    Dernier message: 21/09/2004, 17h45
  3. [LG]Manipulation de fichiers
    Par yffick dans le forum Langage
    Réponses: 29
    Dernier message: 10/01/2004, 15h04
  4. Manipulation de fichiers - gestion d'extensions
    Par ulukai dans le forum Linux
    Réponses: 13
    Dernier message: 02/07/2003, 15h28
  5. Réponses: 2
    Dernier message: 18/01/2003, 17h06

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