Créer un vecteur de termes à partir d'un dossier de fichiers texte

Résolu
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015 - 2 août 2010 à 19:38
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015 - 3 août 2010 à 17:31
bonjour,
pour avoir une liste contenant les termes de tous les fichiers dans un dossier, j'ai écrit ce code.
la liste que j'ai obtenue contient les termes d'un seul fichier répétés n fois (n étant le nombre de fichier dans le dossier in) alors qu'elle doit contenir les termes de tous les fichiers.
mon code me parait juste et j'ai pas pu savoir d'où la faute.
#include <dirent.h>
#include <string>
#include <vector>
#include <fstream>
#include 
// créer un vecteur de termes à partir d'un fichier texte
void fillVector(std::vector<std::string>& liste, const std::string& filename)
{
  std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
  liste.push_back(s);
}

 int main()
 {
   std::vector<std::string>::iterator iter;
   std::vector<std::string>::iterator iter2;
   std::vector<std::string> liste;
   std::vector<std::string> liste2;
   static const std::string folder = "in";
   DIR* rep = opendir(folder.c_str());

if (rep)
  {  struct dirent* lecture;

  while ((lecture = readdir(rep)))
{
  fillVector (liste, lecture->d_name);
//créer un vecteur (liste2)de termes à partir d'un dossier de fichiers texte
  for (iter=liste.begin(); iter!=liste.end(); iter++)
 liste2.push_back(*iter);
 }
closedir(rep);

   }
 for (iter2=liste2.begin(); iter2!=liste2.end(); iter2++)
  std::cout << *iter2 << " ";
  std::cout<<std::endl;
  system("pause");
  return (0);
  }

Pourrais-je avoir votre aide svp?

4 réponses

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
3 août 2010 à 10:32
Plusieurs erreurs:
- La première liste contient déjà ce que tu veux, inutile de remettre une copie dans un autre vecteur. Qui plus est, tu remets des doublons dedans, car la première liste n'est pas effacé. Autant ne gardé qu'une liste.
- Tu as oublié de vérifier que le fichier en cours n'était pas "." ou ".." (Sous Linux, il faut le faire sinon ça plante).
- Vérifie bien la réussite de l'ouverture de ton fichier.

Erreurs de style:
- Inutile de déclarer 2 iter. Un seul suffit, tu aurais pu le réutiliser.
- iter++ et ++iter,; ce n'est pas pareil ! iter++ veut dire: faire une copie, incrémenter, puis réassigner (équivaut à iter = iter + 1). Alors que ++iter veut dire: ne pas faire de copie et directement assigner la valeur. ++iter est donc beaucoup beaucoup plus rapide. D'une manière générale, préfère toujours ++valeur à valeur++.
- Découpe ton code en petites fonctions. Ici, je ne te l'ai pas fait, mais tu devrais avoir une fonction qui affiche le contenu d'un vecteur, et une fonction qui remplit un vecteur en fonction d'un nom de répertoire (donc sortir le milieu du code de main dans une fonction).
Le main devrait ressembler à ça:
std::vector<std::string> liste;
getTermFromDirectory(liste, folder);
displayVector(liste);



Petite correction de ton code,
#include <dirent.h>
#include <string>
#include <vector>
#include <fstream>
#include 

// créer un vecteur de termes à partir d'un fichier texte
void fillVector(std::vector<std::string>& liste, const std::string& filename)
{
  std::ifstream entree(filename.c_str());
  if (!entree)
  {
    std::cerr << "Unable to read the file" << std::endl;
    return;
  }

  std::string s;
  while (entree >> s)
    liste.push_back(s);
}

int main()
{
  typedef std::vector<std::string>::const_iterator iter;
  static const std::string folder = "in";

  std::vector<std::string> liste;
  DIR* rep = opendir(folder.c_str());

  if (rep)
  {
    struct dirent* lecture;
    while ((lecture = readdir(rep)))
    {
      std::string filename = lecture->d_name;
      if (filename != "." && filename != "..")
fillVector (liste, folder + "/" + filename);
    }
    closedir(rep);
  }

  for (iter it = liste.begin(); it != liste.end(); ++it)
    std::cout << *it << " ";
  std::cout << std::endl;

  return (0);
}



________________________________________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
3
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
3 août 2010 à 15:08
Pas besoin de faire un "removeDoublon". Il y a une collection qui s'appelle le std::set qui est sert à éviter les doublons. Tu te fais une fonction qui remplit un std::set à partir d'un fichier, et tu copies l'intégralité de chacun des std::set dans un std::vector.

En gros, au lieu d'avoir: "vector + removeDoublon + vector", tu auras: set + vector.

________________________________________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
3
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
3 août 2010 à 15:04
bonjour,
merci bien pour votre aide,
en fait, j'ai fait 2 listes car je veux éliminer les doublons au sein du même fichier, donc j'ai fait une fonction removeDoublon que j'ai appelé après avoir remplis la 1ère liste, et puis je remplis la deuxième liste sans éliminer les doublons.
(i.e si un mot existe plusieurs fois dans le meme fichier ne laisser qu'une seule occurrence mais s'il existe une fois dans plusieurs fichiers garder toutes occurrences.)
si je fais une seule liste et j'exécute removeDoublon j'aurais pas le résultat voulu.
voilà la fonction removeDoublon
void removeDoublon(std::vector<std::string> & liste)
{
        bool bFound=false;
std::vector<std::string> final;
std::vector<std::string>::iterator iterListe, iterFinal;
    // Test de la validité de la liste
    if (liste.empty())
        return;
    // Init de la liste résultat
    final.push_back(*liste.begin());
    for (iterListe=liste.begin()+1; iterListe!=liste.end(); iterListe++)
    {
        // Recherche si ce n'est pas un doublon
bFound=false;
        for (iterFinal=final.begin(); iterFinal!=final.end() && !bFound; iterFinal++)
        {
            if (0==iterListe->compare(*iterFinal))
              // C'est un doublon, on passe à la chaîne suivante
                   bFound=true;
         }
        if (!bFound)
        {
            // Ce n'est pas un doublon, on l'ajoute à la liste finale
            final.push_back(*iterListe);
        }
    }
    liste=final;
}
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
3 août 2010 à 17:31
c'est vrai que set permet d'éliminer les doublons donc pas besoin de removeDoublon, mais lorsque j'ai'appliqué ceci sur mon premier code avec quelques corrections j'ai obtenu la liste finale sans doublons ce qui est le contraire de ce que j'ai voulu.
0
Rejoignez-nous