Comparer deux fichiers

boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 25 août 2009 à 20:14
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 28 sept. 2009 à 08:44
Bonjour,

J'ai deux fichiers "exemple.txt" et "essai.txt"
J'aime afficher les lignes qui existent dans "exemple.txt" et qui n'existent pas dans "essai.txt"
c'est comme une sorte de la différence.

Chaque ligne de fichier contient une chaine de caractère.
Mon idée :
pour chaque ligne de "exemple.txt" je teste si elle existe dans "essai.txt".
Si oui je l'affiche.

Le problème que on peut trouver la même chaine de caractère de "exemple.txt" mais dont l'ordre des mots formant cette chaine est différent de celui dans "essai.txt"

on affiche la chaine autant qui se compose de mêmes mots.

Soit le fichier "exemple.txt"

nom prenom
nom age
nom prenom age
nom emploi
age emploi
prenom age empoi
nom age emploi
nom prenom emploi
nom prenom age emploi


Soit le fichier "essai.txt"

nom
prenom
age
emploi
age nom
nom age prenom
nom emploi
age emploi
prenom age empoi
nom prenom emploi
nom prenom age emploi


le résultat souhaité est:

nom prenom
nom age
nom age emploi


Comment on obtient ce résultat ?

Merci.
A voir également:

108 réponses

nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 37
25 août 2009 à 20:49
Salut,

Ton résultat semble faut.

En c#, je chargerai les données dans un hastable
ou un autre type de collections

Et je regarderais si la premiere collection contient l'élément courant.

Apres pour l'ordre il y a plusieurs possibilités.
Tu compares les valeurs des tableaux

par exemple.

Désolé c'est en c# mais les collections existent en C++
alors il reste plus que les algos a faire.

Bon dev.
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
26 août 2009 à 09:03
bonjour,
Je vous explique ma demande.
Soit le premier fichier fichier "f.txt":
nom prenom
nom age
nom prenom age
nom emploi
age emploi
prenom age emploi
nom age emploi
nom prenom emploi
nom prenom age emploi

Soit le deuxième fichier "f2.txt":

nom
prenom
age
emploi
age nom
nom age prenom
nom emploi
age emploi
prenom age emploi
nom prenom emploi
nom prenom age emploi

votre solution donne:
nom prenom
nom age
nom prenom age

C'est à dire les lignes qui appartiennent à "f.txt" et n'appartiennent pas à "f2.txt"


Mais, moi je cherche les lignes qui appartiennent à "f.txt" et n'appartiennent pas à "f2.txt"
avec les mots de chaque ligne ne sont pas les mêmes
quelque soit l'ordre.

par exemple,
Dans la ligne de "f.txt":
nom age
est le même que dans "f2.txt" :
age emploi

car les deux lignes ont le même ensemble des mots {nom, age}

Donc le résultat ne contient pas la ligne: nom age


de même Dans la ligne de "f.txt":
nom prenom age
est le même que dans "f2.txt" :
nom age prenom


Enfin en se basant sur l'hypothèse que on compare les lignes qui ont les mêmes mots quelque soit l'ordre

Donc on obtient comme résultat:
nom prenom
nom age emploi

Avez-vous une proposition car j'ai trouvé une difficulté de dire deux lignes sont les mêmes avec leurs mots qui forment ces deux lignes dans un ordre différent ?


Merci.
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
26 août 2009 à 10:37
Voici une l'une des méthodes possibles:

- Créer une fonction "bool diffLine(std::vector<std::string> > a, std::vector<std::string> > b)" qui compare deux tableaux de string. Celle-ci tri par ordre alphabétique les deux tableaux, avant de vérifier qu'ils sont identiques.
- Créer une fonction "std::string getLine(std::ifstream file, int pos)" qui récupère une ligne d'un fichier.
- Créer une fonction "std::vector<std::string> > split(std::string s, char delim = " ")" qui découpe les mots d'une ligne en fonction d'un délimiteur.

Enfin applique la méthode suivante:
Pour la premiere a la derniere ligne du premier fichier (ligneCouranteFichier1) faire
  tableau1 = split(ligneCouranteFichier1);
  Pour la premiere a la derniere ligne du deuxieme fichier (ligneCouranteFichier2) faire
    tableau2 = split(ligneCouranteFichier2);
    Si (diffLine(tableau1, tableau2))
      // les lignes sont identiques
    Sinon
      // les lignes sont differentes
    fin si
  fni pour
fin pour


Ce n'est pas la meilleure méthode, ni la plus optimisé. C'est juste une des méthodes possibles. Il y a dans la STL des transformateur intéressants, pense à y jeter un oeil (notamment pour le tri).
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
26 août 2009 à 18:31
Bonjour,

Mon programme est en C.
1

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

Posez votre question
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
26 août 2009 à 18:34
Oui, et alors ? Je te donne une méthode pour réaliser ce que tu veux. Je ne vais pas le coder à ta place. A toi de l'adapter. Si tu bloques sur un morceau de code, poste ce qui pose problème mais à toi d'essayer de le faire par toi même en t'aidant si tu le désires de la démarche que je viens de décrire dans mon précédent post.
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
26 août 2009 à 18:36
Pour les méthodes du C++, il suffit de les remplacer par du C.

std::string => char*
std::vector<std::string> => char**
std::ifstream => FILE

La méthode reste exactement la même.
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
27 août 2009 à 09:43
Bonjour,

Je vous explique ma demande.
Je cherche les lignes qui appartiennent à "f.txt" et non pas "f2.txt"
C'est une sorte de différence lignes de "f.txt" moins lignes de "f2.txt"
à condition:
Une ligne de "f.txt" est identique à une ligne de "f2.txt"
si les deux lignes ont la même valeur et le même nombre des mots qui forment les deux lignes quelque soit l'ordre des mots puisque l'ordre des mots n'est pas important dans mon problème.
le plus important c'est : la même valeur et le même nombre

Sinon c'est à dire les deux lignes n'ont pas la même valeur et le même nombre des mots alors dans ce cas les deux lignes sont différentes.

par exemple:
"nom prenom age" = "nom age prenom"

et donc l'ordre est ignoré.

J'espère que je le problème est clair sinon je vous explique encore.

Sachant que chaque ligne du deux fichiers "f.txt" et "f2.txt" est composé d'un seul champ (une chaine de caractères)
Le remplissage de deux fichiers se fait par:
fprintf(fp,"%s",s);  //le fichier "f.txt"
fprintf(fp2,"%s",s); //le fichier "f2.txt"


Je n'arrive pas à implémenter votre solution

J'ai besoin de vos aides

Merci.
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
27 août 2009 à 09:51
J'avais bien compris le problème, inutile de le réexpliquer. La méthode que je t'ai donné peut résoudre celui-ci. A toi de commencer à la coder. Je t'ai découpé cette méthode en plusieurs fonctions. Commence déjà par implémenter celles-ci, et poste les morceaux de code qui pourraient poser problème.
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 août 2009 à 12:07
Bonjour,
Je m'excuse de ma part car le problème est dans l'extension du ficher.
au lieu de lui nommer "f.txt" j'ai le nommer "f.txt.txt".

Effectivement il ne te reste plus qu'à coder "same_word".


J'essaye de coder votre idée mais j'ai trouvé une difficulté de savoir quels sont les paramètres de fonctions citées au dessus et leurs valeurs de retour.

Pouvez vous détailler le code de ces fonctions ?
Je serais très contente pour toute aide.

Merci.
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
31 août 2009 à 16:14
c:\tester_\debug> tester_.exe f.txt f1.txt

Ceci fonctionne chez moi. Si ça ne fonctionne pas chez toi, tu as du faire une erreur quelque part.

[...] de plus moi je n'utilise pas l'exécution ar ligne de commande car j'utilise l'environnement visual studio 2008 pour la compilation et l'exécution ?


Un IDE (ici Visual Studio) n'a jamais empêché de faire la ligne de commande ! Il y a toujours une option pour le faire.

Pouvez vous posté une version de votre solution sans utiliser argc et argv ?

Quant à poster une version sans argv et argc, je pense que tu as les compétences nécessaires pour le faire tout seul.
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
31 août 2009 à 17:49
Bonjour,

Voici une version sans argc et argv.
De plus il y a une boucle pour traiter:
-l'intersection entre f.txt f1.txt
-l'intersection entre f.txt f2.txt
-l'intersection entre f.txt f3.txt

Je connais le nombre de fichiers.
Seulement, j'ai mis N=3 pour voir comment se passe.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 1024

char* strndup(const char *str, size_t n)
{

  char *ret = malloc((n+1) * sizeof (char));

  if (!ret)

    exit(0);


  strncpy(ret, str, n);

  ret[n] = 0;

  return ret;

}


void free_tab(char** t)
{

  char** head = t;

  while (t && *t)
  {

    free(*t);
    t++;
  }


  free(head);

}


char** get_word(const char* str)
{

  char* pos = NULL;
  char** res = NULL;
  int nb = 0;

  do
  {
    int size = 0;
    pos = strchr(str, ' ');

    if (pos)

      size = pos - str;


    else

      size = strlen(str) - 1; // - 1 to get rid of \n 

    nb++;

    res = realloc(res, (nb + 1) * sizeof (char*));

    res[nb -1] = strndup(str,  size);

    str = pos + 1;

  }

  while (pos);

  res[nb] = 0;

  return res;
}




int is_same(const char* const s1, const char* const s2)

{

  char **t1, **t2;

  int ret = 0;

  t1 = get_word(s1);

  t2 = get_word(s2);


  if (t1 && t2)
 {

    char** tab1 = t1;

    char** tab2 = t2;

    int nb = 0;

    int size = 0;

    while (tab1 && *tab1)

    {

      tab2 = t2;

      while (tab2 && *tab2)
      {

if (!strcmp(*tab1, *tab2))

  nb++;

tab2++;

      }


      tab1++;

      size++;

    }



    ret = (nb >= size);

    free_tab(t1);

    free_tab(t2);


  }

  return ret;

}



char** compare_file(const char* filename1, const char* filename2)
{

  FILE *f, *f1;

  char s[MAX_SIZE], s1[MAX_SIZE];

  int a;

  char** res = NULL;

  int nb = 0;

  f = fopen(filename1, "r");

  f1 = fopen(filename2, "r");

  if (f && f1)

  {

    while (fgets(s, MAX_SIZE, f))

    {

      a = 0;

      rewind(f1);

      while (fgets(s1, MAX_SIZE, f1))

      {

if (is_same(s, s1))

{

  a = 1;

  break;

}

      }

      if (!a)
      {

nb++;

res = realloc(res, (nb + 1) * sizeof (char*));

res[nb - 1] = strndup(s, strlen(s) - 1); //* Get rid of the \n 

res[nb] = 0;

      }

    }

    fclose(f);

    fclose(f1);

 }


printf("nb ret=%d\n", nb);


 return res;

}


int main()
{

  char** res = NULL;

  char** pos = NULL;

  char input[32];

  int i ;

 
  for (i 1; i <3; i++)

  {

    sprintf(input,"f%d.txt",i);

    res = compare_file("f.txt",input);

    pos = res;

    printf("Comparing f.txt and %s:\n", input);

    while (pos && *pos)

    {

      printf("%s\n", *pos);

     pos++;

    }

    free_tab(res);

  }



  return 0;

}



La compilation se passe bien mais après l'exécution il y a des affichages ne s'affichent pas et surtout après la fonction "compare_file"

J'ai besoin de votre aide car le résultat final de ce problème n'est pas encore atteinte.

Merci.
1
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
27 août 2009 à 10:01
Bonjour,
Voici un exemple:

Soit le premier fichier fichier "f.txt":
nom prenom
nom age
nom prenom age
nom emploi
age emploi
prenom age emploi
nom age emploi
nom prenom emploi
nom prenom age emploi

Soit le deuxième fichier "f2.txt":

nom
prenom
age
emploi
age nom
nom age prenom
nom emploi
age emploi
prenom age emploi
nom prenom emploi
nom prenom age emploi

Le résultat souhaité:
nom prenom
nom age emploi
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
27 août 2009 à 10:06
Inutile de réecrire à chaque fois le principe. A TOI de coder le truc en C. Si tu bloques, nous t'aiderons, mais personne ne le codera pour toi.
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
27 août 2009 à 11:27
Bonjour,
Voici un premier essai:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{

FILE *f,*f2 ;
char s[1000], s2[1000];

f = fopen("f.txt", "r");
f2 = fopen("f2.txt", "r");
while(fgets(s, 1000, f)!= NULL)
{
 
   rewind(f2);
   while(fgets(s2, 1000, f2)!= NULL)
      if(strcmp(s, s2))
             printf("%s\n",s);
         
   }
fclose(f);
fclose(f2);
return 0;
}


Mais cette solution tient de l'ordre des mots de deux lignes pour chaque fichier.
"nom prenom age" est différent " nom age prenom"

j'ai dit il suffit de changer cette condition: if(!strcmp(s, s2)) par un truc comme if(same_word(s, s2)) .
mais, je trouve difficulté de implémenter
la fonction same_word(s, s2)

Comment je vais modifier cette solution pour ignorer l'ordre.
pour obtenir:

"nom prenom age" = " nom age prenom"

Merci.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
27 août 2009 à 14:09
Effectivement il ne te reste plus qu'à coder "same_word".

Pour ceci, il suffit de découper ta fonction en une série de fonction. Essaie de coder ceci:
- char** split(char* str, delim d = " "); Qui va découper une chaîné de caractère en fonction d'un délimiteur. (Aide toi de la fonction strstr qui est dans string.h).
Ex: "nom prenom age" => un tableau contenant {"nom", "prenom", "age"}
- Ecrit une fonction qui trie les tableaux par ordre alphabétique: void sort(char** tab);
- Ensuite écrit une fonction int cmp_tab(char** tab1, char** tab2), qui va comparer les tableaux entre eux, en les triant au préalable à l'aide la fonction sort faites avant.
- Enfin same_words consiste juste à utiliser toutes les méthodes codées précédemment. Essaie de les coder dans cette ordre.
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 août 2009 à 10:49
Bonjour,
J'ai testé le code suivant :


  #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
  
    int main()
    {
      8. FILE *f,*f2 ;
    char s[1000], s2[1000];
  
  f = fopen("f.txt", "r" );
   f2 = fopen("f2.txt", "r" );
   while(fgets(s, 1000, f)!= NULL)
   {
  
      rewind(f2);
      while(fgets(s2, 1000, f2)!= NULL)
         if(strcmp(s, s2))
                printf("%s\n",s);
          
      }
  fclose(f);
   fclose(f2);
  return 0;

}


La compilation se passe bien. Mais, l'exécution ne passe pas bien puisque il y a une génération de l'exception suivante:

Debug assertion Failed!
Prpgram :
File : f\dd\vctools\crt_bld\self_x86\crt\src\fgets.c
Line : 57

Expression : (str != NULL)



D'où vient cette erreur ?

Merci.
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 août 2009 à 11:05
Tu dois simplement tester si l'ouverture du fichier a réussi ou non.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
  FILE *f, *f2;
  char s[1000], s2[1000];
  char* filename1 = "f.txt";
  char* filename2 = "f2.txt";

  f = fopen(filename1, "r" );
  if (f == NULL)
  {
    printf("Unable to open file %s\n", filename1);
    return 1;
  }

  f2 = fopen(filename2, "r" );
  if (f2 == NULL)
  {
    printf("Unable to open file %s\n", filename2);
    return 1;
  }

  while (fgets(s, 1000, f) != NULL)
  {
    rewind(f2);
    while (fgets(s2, 1000, f2) != NULL)
      if (strcmp(s, s2))
printf("%s\n",s);
  }
  fclose(f);
  fclose(f2);

  return 0;
}
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 août 2009 à 11:39
Bonjour,
Après l'exécution, il m'affiche :

Unable to open file f

Mais, les deux fichiers existent.
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 août 2009 à 11:42
Ton fichier n'est pas trouvé, tout simplement. Vérifie le chemin. Et regarde si le repertoire de travail est correcte.
Met un chemin absolu, au pire du genre "/home//f.txt" (unix), ou "C:\\f.txt" (windows)
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 août 2009 à 11:44
Tu peux aussi utiliser "perror" pour voir l'erreur précise retournée:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
  FILE *f, *f2;
  char s[1000], s2[1000];
  char* filename1 = "z.txt";
  char* filename2 = "z2.txt";

  f = fopen(filename1, "r" );
  if (f == NULL)
  {
    perror(filename1);
    return 1;
  }

  f2 = fopen(filename2, "r" );
  if (f2 == NULL)
  {
    perror(filename1);
g    return 1;
  }

  while (fgets(s, 1000, f) != NULL)
  {
    rewind(f2);
    while (fgets(s2, 1000, f2) != NULL)
      if (strcmp(s, s2))
printf("%s\n",s);
  }
  fclose(f);
  fclose(f2);

  return 0;
}
0
Rejoignez-nous