Nombre de fichiers contenant le même terme dans un répertoire

Résolu
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015 - 25 juil. 2010 à 22:53
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015 - 30 juil. 2010 à 19:01
bonsoir,
ce programme permet de déterminer le nombre total de fichiers dans le répertoire "in"; vérifie si le terme "118" existe dans chaque fichier du répertoire et compte le nombre de fichiers contenant ce terme.
#include <stdio.h>
#include <dirent.h>
#include 
#include <fstream>
#include <string>
using std::ifstream;
using std::string;

int main (void)
{
   DIR *rep = opendir ("in" );

   if (rep != NULL)
 {
  struct dirent *lecture;
  int i=0,j=0, existe=0; // i est le nombre de fichiers dans le répertoire
 // j est le nombre de fichiers contenant le mot 118
// existe prend 1 si le terme 118 existe dans le fichier
  ifstream entree;
  string s;
  while (lecture = readdir (rep))
{
   printf ("%-25s    ", lecture->d_name);
   i++;
   std::ifstream entree (lecture->d_name);
   while ( entree >> s)
{
  if (s == "118")
{ existe=1;
  j++;
  break;
}
}
  if (existe==1)
  std::cout << "existe" << std::endl;
  else std::cout << "non" << std::endl;
  existe=0;
}
  if (j>0)  std::cout << "le nombre de fichier contenant le terme est "<< j << std::endl;
  entree.close();
  closedir (rep), rep = NULL;
   printf ("le nombre de fichiers est : %d\n", i-2);
   }
   
   system ("pause");
   return 0;
} 

le répertoire "in" contient 6 fichiers a,b,c,d,e,f et g dont d,e et f contiennent le terme "118".
le résultat obtenu par ce code est erroné
.                         non
..                        non
a                         non
b                         non
c                         non
d                         non
e                         existe
f                         existe
g                         existe
le nombre de fichiers contenant le terme est 3
le nombre de fichiers est 7

j'espère que vous pouvez m'aider à trouver mes fautes.

10 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
27 juil. 2010 à 15:42
Ton programme plante chez moi. Tu dois faire attention, ignorer les "." et les "..", et vérifier si un fichier à bien été ouvert.
De plus, si tu coupes ton programme en petites fonctions, c'est beaucoup plus lisibles.
Evite les NULL en C++, préfère 0, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp
Ne mélange pas C et C++. Donc oublie les printf au profit des std::cout.

En suivant ce que je viens de te dire, j'ai revu ton programme, et ça va beaucoup mieux:
#include <dirent.h>
#include <stdio.h>
#include 
#include <fstream>
#include 

bool exists(const std::string& filename, const std::string& pattern)
{
  // entree se referme tout seul, lors de la desuction
  // de l'objet ifstream
  std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
    if (s == pattern)
      return true;

  return false;
}

bool isValid(const std::string& path)
{
  return !path.empty() && path != "." && path != "..";
}

int main()
{
  static const std::string folder = "in";

  DIR* rep = opendir(folder.c_str());
  if (rep)
  {
    struct dirent* lecture;
    int nbFile = 0;
    int totalFile = 0;

    while ((lecture = readdir(rep)))
    {
      if (!isValid(lecture->d_name))
continue;

      std::cout << std::left << std::setw(25) << lecture->d_name;
      ++totalFile;
      if (exists(folder + "/" + lecture->d_name, "118"))
      {
std::cout << "existe" << std::endl;
++nbFile;
      }
      else
std::cout << "non" << std::endl;
    }

    if (nbFile > 0)
      std::cout << "Le nombre de fichier contenant le terme est "
<< nbFile << std::endl;

    closedir(rep);
    std::cout << "Le nombre de fichiers est : " << totalFile << 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
28 juil. 2010 à 16:40
Tu ne dois pas essayer de calculer le tf en mettant tout dans la même map.
Tu fais une map par fichier. Pense vraiment à décomposer le plus possible en petite fonction. Plus tu fais de sous fonctions, plus ton code sera facile à réaliser.

J'ai repris ce que tu as fait, et ai juste ajouter une petite correction.
#include <dirent.h>
#include <stdio.h>
#include 
#include <fstream>
#include 
#include <map>

bool exists(const std::string& filename, const std::string& pattern)
{
  // entree se referme tout seul, lors de la desuction
  // de l'objet ifstream
  std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
    if (s == pattern)
      return true;

  return false;
}

bool isValid(const std::string& path)
{
  return !path.empty() && path != "." && path != "..";
}

void fillMap(std::map<std::string, int>& map, const std::string& filename)
{
  std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
    ++map[s];
}

void showTermFrequency(const std::string& filename)
{
  std::map<std::string, int> map;
  fillMap(map, filename);

  int som = 0;
  typedef std::map<std::string, int>::const_iterator iter;
  for (iter it = map.begin(); it != map.end(); ++it)
    som += it->second;

  std::cout << "\tLes tf du document " << filename << std::endl;
  for (iter it = map.begin(); it != map.end(); ++it)
    if (som !=0)
      std::cout << "\t\t* tf du mot " << it->first << " est " << (float)it->second / som << std::endl;
}

int main()
{
  static const std::string folder = "in";

  DIR* rep = opendir(folder.c_str());
  if (rep)
  {
    struct dirent* lecture;
    int nbFile = 0;
    int totalFile = 0;

    while ((lecture = readdir(rep)))
    {
      if (!isValid(lecture->d_name))
continue;

      std::cout << std::left << std::setw(25) << lecture->d_name;
      ++totalFile;
      if (exists(folder + "/" + lecture->d_name, "118"))
      {
std::cout << "existe" << std::endl;
++nbFile;
      }
      else
std::cout << "non" << std::endl;

      showTermFrequency(folder + "/" + lecture->d_name);
      std::cout << std::endl;
    }
    if (nbFile > 0)
      std::cout << "Le nombre de fichier contenant le terme est "
<< nbFile << std::endl;
    closedir(rep);
    std::cout << "Le nombre de fichiers est : " << totalFile << 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
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
26 juil. 2010 à 16:37
bonjour;
je suis encore bloquée, j'ai pas pu connaitre ma faute, le programme me parait juste;
aidez moi svp à connaitre la faute.
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
27 juil. 2010 à 16:14
bonjour,
je suis vraiment incapable de vous remercier car j'étais bloquée pendant 3 jours et j'ai pas pu connaitre ma faute;
j'ai essayé votre code, il m'a donné de bons résultats et je vais tout de suite le lire attentivement pour comprendre ce que vous avez fait.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
27 juil. 2010 à 19:43
je vais encore vous gêner à propos de ce même code
j'ai ajouté une autre fonction et quelques instructions dans le main pour calculer le tf (term frequency)de chaque terme;
void creermap(const std::string& filename)
{ std::map<std::string, int> map;
   std::ifstream entree(filename.c_str());
   std::string s;
  while (entree >> s)
   ++map[s];

}

int main()
{.... /*j'ai mis ce code du main juste après l'instruction (std::cout << "non" << std::endl;)*/
creermap(folder + "/" + lecture->d_name);
    typedef std::map<std::string, int>::const_iterator iter;
  for (iter it = map.begin(); it != map.end(); ++it)
 som = som+ it->second;
  if (strcmp (lecture->d_name, ".") !=0 && strcmp (lecture->d_name, "..") !=0)
  sortie << " les tf du document " << lecture->d_name << std::endl;
  for (iter it = map.begin(); it != map.end(); ++it)
 if (som !=0)
  sortie << "tf du mot " << it->first << " est " << (float)it->second / som << std::endl;
som=0;
}

....}

j'obtiens dans le résultat
les tf du document a.txt
les tf du document b.txt
les tf du document c.txt
les tf du document d.txt
les tf du document e.txt
les tf du document f.txt
les tf du document g.txt

ce qui lui manque les tf des mots,
ce serait vraiment génial si j'aurais encore votre aide, et merci.
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
28 juil. 2010 à 00:57
bonsoir,
j'ai essayé meme autrement, sans l'utilisation d'une fonction,
j'ai ajouté dans le main ces instructions:
while (entree >> s)
   ++map[s];
typedef std::map<std::string, int>::const_iterator iter;
  for (iter it = map.begin(); it != map.end(); ++it)
 som = som+ it->second;
  if (strcmp (lecture->d_name, ".") !=0 && strcmp (lecture->d_name, "..") !=0)
  sortie << " les tf du document " << lecture->d_name << std::endl;
  for (iter it = map.begin(); it != map.end(); ++it)
 if (som !=0)
  sortie << "tf du mot " << it->first << " est " << (float)it->second / som << std::endl;
som=0;

le résultat obtenu est encore erroné,
pour les 5 premiers fichiers,le résultat est bon, et pour les 2 derniers fichiers j'ai obtenu les mots et les tf du fichier précédent, comme si la lecture n'a pas été faite pour les 2 derniers fichiers.

j'espère avoir votre aide.
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
28 juil. 2010 à 17:52
tellement votre méthodologie est supère, lorsque j'ai lu le code, j'ai dit il est si simple, malgré que j'ai tant essayé et ça n'a pas marché.
j'ai juste une petite question, pourquoi vous avez mis le map en paramètre dans la fonction fillMap?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
28 juil. 2010 à 17:59
J'ai mis ceci pour éviter une copie couteuse inutile.
En effet, si j'avais retourné une std::map, il y aurait eu copie. Si j'avais retourné l'adresse d'une std::map, alors j'aurais pointé sur une zone qui aurait été libéré au sortir de la fonction et ça aurait planté.

J'aurais alors pu faire un "new std::map" et retourner le pointeur, puis le libérer. Mais j'ai préféré éviter cela.
Donc la map se fait remplir par la fonction, et se détruit toute seul.

________________________________________________________________________
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
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
28 juil. 2010 à 18:08
c'est vraiment super ce que vous dites, merci pour toutes ces explications.
0
cs_mervat Messages postés 90 Date d'inscription samedi 5 juin 2010 Statut Membre Dernière intervention 6 mars 2015
30 juil. 2010 à 19:01
bonjour,
j'ai voulu modifier l'ancien code pour y ajouter le nombre de fichiers où apparait chaque terme, l'affichage que je voulais avoir pour chaque mot c'est:
tf du mot ... est ...
nombre de fichiers contenant ce terme est ...

voilà le nouveau code qui me donne un résultat erroné,
pouvez vous m'aider à savoir comment le faire car j'ai pas pu calculer le nbre de fichiers contenant chaque terme et au même temps avoir l'affichage désiré.
#include <dirent.h>
#include <stdio.h>
#include 
#include <fstream>
#include 
#include <map>
#include<string>

bool exists(const std::string& filename, const std::string& pattern)
{
   std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
if (s == pattern)
  return true;

  return false;
}

bool isValid(const std::string& path)
{
  return !path.empty() && path != "." && path != "..";
}

void fillMap(std::map<std::string, int>& map, const std::string& filename)
{
  std::ifstream entree(filename.c_str());
  std::string s;
  while (entree >> s)
    ++map[s];
}

void fillMaps(std::map<std::string, int>& maps)
{ std::string s;
  static const std::string folder = "in";
  DIR* rep = opendir(folder.c_str());
  if (rep)
  {  struct dirent* lecture;

  while ((lecture = readdir(rep)))
{
  if (!isValid(lecture->d_name))
continue;
std::ifstream entree(lecture->d_name);
while (entree >> s)
++maps[s];
  }
closedir(rep);

  }
  }

void showTermFrequency(const std::string& filename)
{
  std::map<std::string, int> map;
  fillMap(map, filename);

  int som = 0;
  typedef std::map<std::string, int>::const_iterator iter;
  for (iter it = map.begin(); it != map.end(); ++it)
som += it->second;

  std::cout << "\tLes tf du document " << filename << std::endl;
  for (iter it = map.begin(); it != map.end(); ++it)
    if (som !=0)
      std::cout << "\t\t* tf du mot " << it->first << " est " << (float)it->second / som << std::endl;
}

int main()
{ std::map<std::string, int> maps;
  static const std::string folder = "in";

  DIR* rep = opendir(folder.c_str());
  if (rep)
  {
struct dirent* lecture;
    int nbFile = 0;
    int totalFile = 0;
fillMaps(maps);
typedef std::map<std::string, int>::const_iterator iter;
 for (iter it = maps.begin(); it != maps.end(); ++it)
  {
   while ((lecture = readdir(rep)))
{
   if (!isValid(lecture->d_name))
 continue;

std::cout << std::left << std::setw(25) << lecture->d_name;
   ++totalFile;
  
   if (exists(folder + "/" + lecture->d_name, it->first))
{
   std::cout << "existe" << std::endl;
   ++nbFile;
}
   else
std::cout << "non" << std::endl;

   showTermFrequency(folder + "/" + lecture->d_name);
   std::cout << std::endl;
}
   if (nbFile > 0)
   std::cout << "Le nombre de fichier contenant le terme " <<  it->first <<" est " << nbFile << std::endl;
  }
closedir(rep);
std::cout << "Le nombre de fichiers est : " << totalFile << std::endl;
  }

  system("pause");
  return 0;
}
0
Rejoignez-nous