Comparer deux fichiers

Signaler
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
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.

108 réponses

Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
Mon problème concernant le critère de la comparaison de deux fichiers a été modifié.
Je vous explique :
On n'affiche pas dans la console les lignes identiques.
la condition que deux lignes sont identiques ne tient pas de l'ordre par exemple:
"a b c" = "b c a"

Mais, une autre condition qui s'ajoute :on n'affiche pas les lignes de "f.txt" qui sont inclus dans "f2.txt"
par exemple:
"a c" est inclue dans "b c a"
"b c" est inclue dans "b c a"

Donc ou lieu d'obtenir comme résultat :
a b
b c
b d
c d
a b d
b c d
a c d
a b c d

Alors si on ajoute la condition d'inclusion, on va obtenir le résultat suivant:

b d
c d
a b d
b c d
a c d
a b c d

comment noua allons adapter votre idée pour tenir compte des deux conditions:l'ignorance de l'ordre et la condition d'inclusion ?

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Il n'y a pas grand chose à changer. La seule différence réside dans la fonction de comparaison de tableau, qui au lieu de trier alphabétiquement les éléments de chaque tableau afin d'en faire la comparaison, ne triera rien, et vérifiera l'inclusion.
Dans l'ordre:
- Code la méthode "split" que je t'ai décrit
- Ne code plus la méthode "sort"
- Code la méthode "cmp_tab".
- Code "same_word"
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
Vous avez bien compris le problème.
J'ai voulu composer mon problèmes en sous problèmes pour que soit lisible.

Votre idée marche pour deux fichiers et donc je vais l'exploiter pour autres fichiers.
Je vous explique le problème en totalité:

J'ai un fichier de base qui doit être exister qui s'appelle "f.txt"
Soit le fichier "f.txt":
a b
a c
a d
b c
b d
c d
a b c
a b d
b c d
a c d
a b c d

et j'ai d'autres fichiers qui leur nombre varie. Mais au moins j'ai un et je peux avoir N fichiers.
Supposons que on a N=3.
Donc on a 3 fichiers respectivement: "f1.txt", "f2.txt" et "f3.txt"
Soit "f1.txt" :
a
d a
c a
b c a

Soit "f2.txt" :
a
c
b
d
b a
d a
b c
d c
b c a

Soit "f3.txt" :
a
b
c
c a
d a
b a
b c
b c a

Je voudrais chercher comme j'ai dit avant les lignes qui appartiennent au "f.txt" et qui vérifient les deux conditions c'est à dire : l'ignorance de l'ordre et inclusion.

Je vais appliquer votre idée successivement entre:
- "f.txt" et "f1.txt"
- "f.txt" et "f2.txt"
- "f.txt" et "f3.txt"

C'est bon j'obtiens le résultat pour:
- "f.txt" et "f1.txt"
b d
c d
a b d
b c d
a c d
a b c d

- "f.txt" et "f2.txt"
b d
a b d
b c d
a c d
a b c d

- "f.txt" et "f3.txt"
b d
c d
a b d
b c d
a c d
a b c d

Le travail est de chercher l'intersection entre ces résultats obtenus.
Mon idée est de sauvegarder le résultat d'appel de la fonction "is_same()" c'est à dire au lieu d'afficher dans la console alors c'est mieux de sauvegarder le résultat dans un fichier ou un tableau.
Puis on fait l'intersection entre les résultats sauvegardés .

Le résultat souhaité obtenu à la fin est :
b d
a b d
b c d
a c d
a b c d

Enfin, nous cherchons dans ce résultat la ligne qui n'est pas incluse dans les autres lignes de ce même résultat.
on a :
"a b d" contient "b d"
"b c d" contient "b d"
"a b c d" contient "b d"

Et donc nous obtenons le résultat final de ce problème:
b d
a c d

Que pensez vous de cette idée ?
Que proposez vous comme structure de donnée pour sauvegarder les résultats obtenus entre deux fichiers puis pour faire l'intersection entre ces résultats ?
Pouvez vous poster votre solution pour que je vois comment je vais l'exploiter ?

J'ai besoin de vos aides.

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
L'idée est correcte. Effectivement, tu vas devoir stocker le résultat de la fonction de comparaison entre deux fichiers.
Pour cela, créer une fonction "char** cmp_file(char* filename1, char* filename2)". Celle-ci renverra un tableau de chaînes de caractère contenant le résultat.
Une fois cette fonction faite, on l'appelle pour chacun des fichiers, et on fait l'intersection entre les différents tableaux obtenus.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Voici un essai qui n'est pas complet :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define F_NAME "f.txt"
#define F1_NAME "f1.txt"
#define F2_NAME "f2.txt"
#define F3_NAME "f3.txt"
#define MAX_SIZE 1024

int main(void)
{
    FILE *f, *f1,*f2,*f3;
    char s[MAX_SIZE], s1[MAX_SIZE];
    int a;
f = fopen(F_NAME, "r"); 
f1 = fopen(F1_NAME, "r");
f2 = fopen(F2_NAME, "r");
f3 = fopen(F3_NAME, "r");

    if(f && f1 && f2 && f3)
    {
        for (i=1;i<=3;i++)
       {
        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)
              printf(s);
        }
        fclose(f);
 fclose(f1);
fclose(f2);
fclose(f3);
    }

    return 0;
}


J'ai réfléchi beaucoup et je suis bloquée.
- Comment je vais dans la boucle traiter le reste de fichier "f2.txt" et "f3.txt" puisque la boucle au dessus traite seulement "f1.txt" ?

- Je n'arrives pas à sortir de la fonction "is_same"
C'est possible de fournir cette fonction ?

- Dans le "main" au dessus, où je vais sauvegarder le résultat de comparaison ? entre :
"f.txt" et "f1.txt"
"f.txt" et "f2.txt"
"f.txt" et "f3.txt"

Je serais très reconnaissante pour votre aide.

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Tu n'écoutes pas ce que je dis. Tu dois découper ton code en fonction plus simple.
Code les fonctions dans l'ordre que je t'ai donné, et tout ira bien. On verra la structure globale après.

Non, je ne te donnerai pas le fonction is_same. Cette fonction représente 80% du travail, et c'est à toi de le réaliser.

Pour le résultat des comparaisons, il suffit de relire ce que j'ai déjà écrit. Je te l'ai déjà expliqué.

Code la fonction split décrite précedemment.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
Voici mon essai pour la fonction "is_same"

int is_same(const char *s1, const char *s2)
{
    char **t1, **t2;
    size_t size1 count_word(s1), size2 count_word(s2);
    int ret = 0;

    t1 = malloc(size1 * sizeof(char*));
    t2 = malloc(size2 * sizeof(char*));

    if(t1 && t2)
    {
        size_t i, j;
        int a;

        get_word(t1, s1);
        get_word(t2, s2);

        ret = 1;

        for(i = 0; i < size1; i++)
        {
            a = 0;

            for(j = 0; j < size2; j++)
                if(!strcmp(t1[i], t2[j]))
                    a = 1;

            if(!a)
                ret = 0;
        }

        free_tab(t1, size1), free_tab(t2, size2);
    }
    else
        exit(0);
    return ret;
}



Dans ce code, ils me manquent les deux fonctions "count_word" et
"get_word".
get_word(): permet d'extraire les mots de chaque ligne dans un tableau
count_word(): permet de compter le nombre de mots dans une ligne.

Comment on peut améliorer ce code pour obtenir au résultat souhaité ?

Je serais très contente pour toute aide.

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Je modifierais juste une partie du code.
En effet, en l'état tu peux dire si l'un des éléments est présent dans l'autre, mais pas l'ensemble.
Est ce que "a c" est contenu dans "a d" ?
Si oui, alors ton code est correcte, sinon il faut faire ceci:

        /* Nombre d'élément ayant été trouvé */
        nb = 0; 
        for (i = 0; i < size1; i++)
            for (j = 0; j < size2; j++)
                if(!strcmp(t1[i], t2[j]))
                    nb++;
        ret (nb size1);
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonsoir,
Est ce que "a c" est contenu dans "a d" ?


Non. "a c " n'est pas contenu dans "a d ".
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
Voici un essai de comparaison entre deux fichiers en respectant les deux condistions:
- L'ignorance de l'ordre
- L'inclusion

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

#define F_NAME "f.txt" 
#define F1_NAME "f1.txt"
#define MAX_SIZE 1024

char * mstrndup(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, size_t len)
{
    if(t)
    {
        size_t i;
        for(i = 0; i < len; i++)
            free(t[i]);
        free(t);
    }
}

size_t count_word(const char *str)
{
    size_t n = 0;
    int a;

    while(*str)
    {
        a = 0;
        while(isalpha((unsigned char) *str) && *str) str++, a = 1;
        if(a) n++;
        while(!isalpha((unsigned char) *str) && *str) str++;
    }
    return n;
}

void get_word(char **tab, const char *str)
{
    const char* p = str;
    int a, i = 0;

    while(*str) 
    {
        a = 0;
        while(isalpha((unsigned char) *p) && *p) p++, a = 1;
        if(a)
          tab[i++] = mstrndup(str, p-str);
        while(!isalpha((unsigned char) *p) && *p) p++;
        str = p;
    }
}

int is_same(const char *s1, const char *s2) 
{
    char **t1, **t2;
    size_t size1 count_word(s1), size2 count_word(s2);
    int ret = 0;
   
        t1 = malloc(size1 * sizeof(char*));
        t2 = malloc(size2 * sizeof(char*));

        if(t1 && t2)
        {
            size_t i, j;
            int a;

            get_word(t1, s1);
            get_word(t2, s2);

            ret = 1;

            for(i = 0; i < size1; i++)
            {
                a = 0;

                for(j = 0; j < size2; j++)
                    if(!strcmp(t1[i], t2[j]))
                        a = 1;

                if(!a)
                    ret = 0;
            }

            free_tab(t1, size1), free_tab(t2, size2);
        }
        else
          exit(0);
    
    return ret;
}

int main(void)
{
    FILE *f,*f1 ;
    char s[MAX_SIZE], s1[MAX_SIZE]; 
    int a;

f = fopen(F_NAME, "r");
f1 = fopen(F1_NAME, "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)
              printf(s);
        }
        fclose(f);
 fclose(f1);
    }

    return 0;
}


J'applique cet code sur les deux fichiers respectivement "f.txt" et "f1.txt":
Soit "f.txt" :
a b
a c
a d
b c
b d
c d
a b c
a b d
b c d
a c d
a b c d

Soit "f2.txt" :
a
d a
c a
b c a

ce code nous donne la comparaison entre f et f1 et il affiche dans la console:

b d
c d
a b d
b c d
a c d
a b c d

Je vois que ce code ne reflète pas exactement votre idée. J'ai posé mon essai.
- Que pensez vous ?
- C'est possible que vous posez votre solution peut être plus meilleure que mienne car moi je cherche la solution la plus rapide et consomme le moins de mémoire car je vais évaluer le temps d'exécution de chaque solution ?
- A quoi modifier dans mon code pour obtenir le résultat final comme décrit au dessus qui est l'intersection entre les résultats obtenus pour chaque deux fichiers et pour chercher dans ce résultat final la ligne qui n'est pas incluse dans les autres lignes de ce même résultat ?

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Je te propose une version:
- On se moque de la taille du tableau, car j'ajoute un NULL en dernier élément de celui-ci. Ce qui permet de ne pas à se soucier de la taille, et surtout de ne faire qu'une passe sur le tableaux (et pas deux juste pour avoir la taille).
- Juste corriger un petit truc, dont je t'ai déjà parlé. En effet, si "a c" n'est pas dans "a d", alors il faut vérifier que tout les éléments correspondent et pas seulement un. Sinon tu risques de dire qu'ils sont identiques.
- Enfin, j'ai juste créer une fonction compare file qui reprend ton code, afin de créer un main plus propre, qui prend en compte les arguements de la ligne de commande.
- J'ai viré ton is_alpha, puisqu'on sait que le caractère de séparation est forcément un espace. La fonction strchr fait le travail de recherche, inutile de le faire soi même.

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

  return res;
}

int main(int argc, char** argv)
{
  char** res = NULL;
  char** pos = NULL;
  int i = 0;

  if (argc <= 2)
  {
    printf("Usage : %s file [files]\n", argv[0]);
    return 1;
  }

  for (i = 2; i < argc; ++i)
  {
    res = compare_file(argv[1], argv[i]);
    pos = res;
    printf("Comparing %s and %s:\n", argv[1], argv[i]);
    while (pos && *pos)
    {
      printf("%s\n", *pos);
      pos++;
    }
    free_tab(res);
  }
  return 0;
}
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Supposons que on a les 4 fichiers comme décrits au dessus: "f.txt", "f1.txt", "f2.txt" et "f3.txt".

- Comment vous exécutez ce programme par ligne des commandes ?

- Quel est le résultat de ce programme ?

- Qu'est ce que vous changez dans ce programme si nous n'utilisons pas argc et argv c'est à dire on utilise les noms de fichiers ?
A titre d'information, toujours on a un fichier de base "f.txt" et N fichiers qui sont l'objet de comparaison ici on a 3 fichiers: "f1.txt" , "f2.txt" et "f3.txt" .

- Est ce que ce programme permet de faire l'intersection entre chaque résultat de chaque comparaison entre deux fichiers et permet t-il de trouver le résultat final ?
Enfin, nous cherchons dans ce résultat(l'intersection des résultats) la ligne qui n'est pas incluse dans les autres lignes de ce même résultat.

Je serais très contente pour vos aides.

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
- Comment vous exécutez ce programme par ligne des commandes ?
./a.out f.txt f1.txt

En gros : programme liste des fichiers en commençant par f.txt

- Quel est le résultat de ce programme ?

Le même que le tien.

- Qu'est ce que vous changez dans ce programme si nous n'utilisons pas argc et argv c'est à dire on utilise les noms de fichiers ?

On laisse à l'utilisateur le choix du nom des fichiers, plutôt que de lui imposer des noms. De plus, il peut mettre autant de fichiers qu'ils le souhaite et pas seulement 2 ou 3.

- Est ce que ce programme permet de faire l'intersection entre chaque résultat de chaque comparaison entre deux fichiers et permet t-il de trouver le résultat final ?

Non, ce que j'ai écrit n'est qu'une version un petit remaniée de ton code.
Il te reste bien évidemment à faire l'intersection des résultats. Chaque comparaison de fichiers est stocké dans un char** (regarde le code du main). A toi de faire l'intersection entre ces différents tableaux.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
En gros : programme liste des fichiers en commençant par f.txt

lorsque je tape la commande suivante :
./tester_ f.txt f1.txt
avec "tester_" est le nom de programme

alors ceci ne passe pas bien alors j'ai le message suivant:
'.' n'est pas reconnu en tant que commande interne ou externe, un programme exécutable ou un fichier des commandes

- Comment se fait sur windows ?
- quel est le racine à mettre pour lancer un programme par lignes des commandes ?

On laisse à l'utilisateur le choix du nom des fichiers, plutôt que de lui imposer des noms. De plus, il peut mettre autant de fichiers qu'ils le souhaite et pas seulement 2 ou 3.



En réalité dans mon travail ces fichiers sont générés automatiquement et de plus je connais le nombre N qui présentent l'objet de comparaison.
Ici, j'ai mis N 3 pour voir comment on résoudre le problème puisque si la solution marche pour N 3 alors elle marche pour N = 20.

Dans mon programme "main", je ne vais pas utiliser argc et argv.
Pouvez vous me poster la version qui utilise directement le nom des fichiers ?


pos = res

- ceci c'est une simple copie d'un tableau dans un autre ?
- pourquoi pas n'utiliser directement "res" sans passer par "pos"


while (pos && *pos)

- Quelle est la différence entre pos et *pos ?
- Quel est le rôle de cette boucle ?

Supposons comme décrit avant on a un fichier de base "f.txt" et N=3 autres fichiers qui sont objet de comparaison alors d'après le dernier code à chaque fois le contenu "res" va être perdu
si on fait la comparaison entre "f.txt" et "f1.txt" et on sauvegarde le résultat dans "res".
dans l'itération suivante on fait la comparaison entre "f.txt" et "f2.txt" et on sauvegarde le résultat dans "res" et donc l'ancien contenu sera écrasé
de même si on fait la comparaison entre "f.txt" et "f3.txt" .
le "res" va contenir le résultat de la dernière comparaison .
et donc on ne peut pas faire une intersection.

comment on va résoudre ce problème ?

Merci.

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

voici mon essai concernant la modification de "main()" c'est à dire au lieu de travailler avec argc et argv alors je voulais directement utiliser les noms des fichiers.


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 il n' y pas d'affichage après l'exécution.
J'ai fait des tests de "printf" alors j'ai remarqué que même l'affichage suivant n'a pas lieu:
    printf("Comparing f.txt and %s:\n", input);


Je crois le plus probable que la fonction compare_file ne s'exécute pas complètement.

Avez-vous une proposition ?

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
lorsque je tape la commande suivante :
./tester_ f.txt f1.txt
avec "tester_" est le nom de programme

alors ceci ne passe pas bien alors j'ai le message suivant:
'.' n'est pas reconnu en tant que commande interne ou externe, un programme exécutable ou un fichier des commandes
- Comment se fait sur windows ?
- quel est le racine à mettre pour lancer un programme par lignes des commandes ?


C'est normal, je suis sous unix. Sous windows il suffit juste de se mettre dans le bon repoertoire et de ne pas mettre "./" devant.
Par exemple: tester_ f.txt f1.txt

En réalité dans mon travail ces fichiers sont générés automatiquement et de plus je connais le nombre N qui présentent l'objet de comparaison.
Ici, j'ai mis N 3 pour voir comment on résoudre le problème puisque si la solution marche pour N 3 alors elle marche pour N = 20.

Ok, mais c'est vraiment dommage de faire quelque chose de fixe, alors qu'on peut faire un truc générique facilement.

pos = res
- ceci c'est une simple copie d'un tableau dans un autre ?

NON.
Ce n'est pas une copie de tableau. C'est une copie du pointeur sur le tableau. pos et res pointeront sur le même tableau qui est en mémoire.

- pourquoi pas n'utiliser directement "res" sans passer par "pos"

Pour ne pas perdre la "tête". Pour pouvoir faire un free juste après il faut donner l'adresse du début du tableau, pas la fin. Donc j'utilise "pos", afin de ne pas perdre l'adresse de "res".


while (pos && *pos)
- Quelle est la différence entre pos et *pos ?

"pos" c'est un pointeur sur le tableau.
"*pos" c'est la case en cours du tableau.

Exemple:
char** t = {"abcd", "rty", "xyz", NULL};

t => adresse du tableau t.
*t => adresse de "abcd". Equivaut à *(t + 0) => t[0]
**t => 'a'. Equivaut à *(*(t + 0) + 0) => t[0][0]


- Quel est le rôle de cette boucle ?

Afficher ce qui est contenu dans le tableau "res".


Supposons comme décrit avant on a un fichier de base "f.txt" et N=3 autres fichiers qui sont objet de comparaison alors d'après le dernier code à chaque fois le contenu "res" va être perdu

C'est normal, je ne t'ai pas écrit la solution. J'ai juste remanié ton code. A toi de faire la dernière étape. Essaie au moins de trouver une idée. Ensuite je t'aiderais si tes idées ne te sont pas satisfaisante.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

voici mon essai concernant la modification de "main()" c'est à dire au lieu de travailler avec argc et argv alors je voulais directement utiliser les noms des fichiers.

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 il n' y pas d'affichage après l'exécution.
J'ai fait des tests de "printf" alors j'ai remarqué que même l'affichage suivant n'a pas lieu

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




Je crois le plus probable que la fonction compare_file ne s'exécute pas complètement.

Avez-vous une proposition ?

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
J'ai testé votre dernier code avec la ligne des commandes.
Mais, il y a aucun affichage sur la console.
J'ai fait des tests de "printf" alors j'ai remarqué que même l'affichage suivant n'a pas lieu
 printf("Comparing f.txt and %s:\n", input);


Je crois le plus probable que la fonction compare_file ne s'exécute pas complètement.

Merci.
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Le code que j'ai t'ai envoyé fonctionne et affiche toujours quelque chose. Si tu as apporté des modifications, vérifie que ce celles-ci soient correctes.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
J'ai testé votre dernier code avec la ligne des commandes sans faire aucune modification.
Mais, il y a aucun affichage sur la console.

Voici la ligne de commande:
c:\tester\debug> tester f.txt f1.txt


Voici dernier code posté:

#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(int argc, char** argv)

{

  char** res = NULL;

  char** pos = NULL;

  int i = 0;



  if (argc <= 2)

  {

    printf("Usage : %s file [files]\n", argv[0]);

    return 1;

  }



  for (i = 2; i < argc; ++i)

  {

    res = compare_file(argv[1], argv[i]);

    pos = res;

    printf("Comparing %s and %s:\n", argv[1], argv[i]);

    while (pos && *pos)

    {

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

      pos++;

    }

    free_tab(res);

  }

  return 0;

}


Qu'est ce que il affiche ce code chez vous ?

Merci.