Nombre de fichiers contenant le même terme dans un répertoire [Résolu]

Signaler
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015
-
cs_mervat
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015
-
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

Messages postés
3802
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
9 janvier 2020
93
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
Messages postés
3802
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
9 janvier 2020
93
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
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

bonjour;
je suis encore bloquée, j'ai pas pu connaitre ma faute, le programme me parait juste;
aidez moi svp à connaitre la faute.
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

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.
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

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.
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

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.
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

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?
Messages postés
3802
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
9 janvier 2020
93
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
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

c'est vraiment super ce que vous dites, merci pour toutes ces explications.
Messages postés
90
Date d'inscription
samedi 5 juin 2010
Statut
Membre
Dernière intervention
6 mars 2015

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;
}