IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

fonction de comparaison de string entre deux fichiers


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut fonction de comparaison de string entre deux fichiers
    Bonjour tout le monde!

    J'ai un problème avec un programme, ce dernier doit ouvrir deux fichiers .txt; une liste de membres et une liste de présence. Il fait appel à une fonction qui recherche le nom du membre dans la liste de présence, si le nom est dedans, il passe au membre suivant, si il ne l'est pas, il s'affiche à l'écran et le programme recommence l'analyse avec le membre suivant.

    Le problème est que mon programme affiche le premier nom qui ne se trouve pas dans les deux listes et c'est tout, je pense (je suis quasi sûr, à vrai dire) que ça vient de ma condition de boucle mais je ne vois pas comment fixer le problème :/

    Une condition totalement différente? Une condition supplémentaire? une autre boucle? ...

    Je précise que je ne suis pas expert en programmation et la manipulation de fichiers est un sujet encore assez flou pour moi, je ne suis qu'étudiant et je n'ai pas vu cette matière...

    Voici mon programme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define LIM 15
     
    void searchName(char*, char*, FILE*, FILE*);
     
    int main()
    {
        char name[LIM];
        char nom[LIM];
        FILE* listeMembres=NULL;
        FILE* listePresences=NULL;
     
        listeMembres = fopen("listeMembres.txt","r");
        listePresences = fopen("listePresences.txt","r");
     
        if(listeMembres != NULL && listePresences != NULL)
        {
            searchName(name, nom, listePresences, listeMembres);
        }
        else
        {
            printf("Impossible d'ouvrir le fichier listeMembres.txt");
        }
        fclose(listeMembres);
        fclose(listePresences);
     
        return 0;
    }
     
    void searchName(char *name,char *nom, FILE *listePresences, FILE* listeMembres)
    {
        fgets(name, LIM, listeMembres);
        fgets(nom, LIM, listePresences);
     
        while(feof(listePresences)==0)
        {
            if(strcmp(name,nom)==0)
            {
                fgets(name, LIM, listeMembres);
                rewind(listePresences);
            }
            else
            {
                fgets(nom, LIM, listePresences);
                if(feof(listePresences))
                {
                    printf("%s",name);
                }
            }
        }
    }
     
     
    /*
    Problèmes :
     
    1. Affiche le premier absent et pas toute la liste d'absents (condition de boucle?)
    2. affiche le dernier nom présent au lieu des absents à partir d'un certain palier
    */
    Toutes informations pouvant aider à régler le problème sont les bienvenues
    Merci d'avance!

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Dans ces cas-là, il ne faut pas hésiter à laisser tomber son clavier (au sens figuré, hein?) et à griffonner un peu de pseudo-code. Pour l'instant tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Tant qu'il y a des noms dans la liste de présence:
      Si c'est le nom du membre:
        Alors on prend le prochain membre et on revient au début de la liste de présence
      Sinon:
        On prend le prochain présent et s'il n'y en a plus on affiche le nom du membre
    Donc mettons qu'on soit à la fin de liste de présence et qu'on ait pas trouvé le nom (ligne 6). Que se passe-t-il? On revient au début de la boucle qui nous dit: si je n'ai plus de nom dans la liste de présence, c'est fini. Du coup, eh bien, c'est fini -après le premier nom si le deuxième n'est pas dans la liste de présence.

    Je dirais qu'il te faut plutôt une double boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Tant qu'il y a des membres:
      trouvé = faux
      Tant qu'il y a des présents:
         si membre = présent: alors trouvé = vrai et break
      si trouvé = faux: print membre
      rewind presents

  3. #3
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    J'ajouterais que si faire la recherche dans le fichier lui-même n'est pas une contrainte de l'énoncé, alors lis tes fichiers d'une traite, stockes leur contenu en mémoire (au moins la liste de présence) puis effectues les opérations de recherche sur tes structure de données. Tu auras ainsi une idée plus claire de ce que tu fais, je pense.

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut
    voici ce que j'ai maintenant comme code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define LIM 15
     
    void searchName(char*, char*, FILE*, FILE*);
     
    int main()
    {
        char name[LIM];
        char nom[LIM];
        FILE* listeMembres=NULL;
        FILE* listePresences=NULL;
     
        listeMembres = fopen("listeMembres.txt","r");
        listePresences = fopen("listePresences.txt","r");
     
        if(listeMembres != NULL && listePresences != NULL)
        {
            searchName(name, nom, listePresences, listeMembres);
        }
        else
        {
            printf("Impossible d'ouvrir le fichier listeMembres.txt");
        }
        fclose(listeMembres);
        fclose(listePresences);
     
        return 0;
    }
     
    void searchName(char *name,char *nom, FILE *listePresences, FILE* listeMembres)
    {
        int find=0;
        fgets(name, LIM, listeMembres);
        fgets(nom, LIM, listePresences);
     
        while(feof(listeMembres)==0)
        {
            find=0;
            while(feof(listePresences)==0)
            {
                if(name==nom)
                {
                    find=1;
                    break;
                }
            }
            if(find==0)
            {
                printf("%s",name);
            }
            rewind(listePresences);
        }
    }
    Sauf que la console reste désespérément vide... elle ne m'affiche plus rien, comme si elle était en travail... sauf qu'elle ne fait rien :/
    Il y a juste le curseur dans la console, pas de return, pas de nom, rien...

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Relis bien tes conditions de boucle, notamment celles de la boucle interne. Il n'y a rien dans le corps de la boucle qui fait évoluer ces conditions (que ce soit celle sur la fin de fichier ou la comparaison de chaines). Donc si ces conditions deviennent vraies avant ou pendant l'exécution de ta boucle, elles le resteront à jamais quoiqu'il arrive. Tu as donc ici un problème algorithmique à résoudre.

    En parlant de la comparaison de chaînes : name==nom n'effectue pas l'opération que tu attends. Cela fonctionne en Python, Java, C#... mais pas en C. Regarde du côté de strcmp.

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Tu as oublié tes fgets

  7. #7
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut
    Incroyable les oublis qu'on peut faire avec la fatigue... xD
    Mais maintenant, tout fonctionne à merveille!
    Merci à tous pour votre aide!

    Voici le code définitif si quelqu'un a le même problème dans le futur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define LIM 15
     
    void searchName(char*, char*, FILE*, FILE*);
     
    int main()
    {
        char name[LIM];
        char nom[LIM];
        FILE* listeMembres=NULL;
        FILE* listePresences=NULL;
     
        listeMembres = fopen("listeMembres.txt","r");
        listePresences = fopen("listePresences.txt","r");
     
        if(listeMembres != NULL && listePresences != NULL)
        {
            searchName(name, nom, listePresences, listeMembres);
        }
        else
        {
            printf("Impossible d'ouvrir le fichier listeMembres.txt");
        }
        fclose(listeMembres);
        fclose(listePresences);
     
        return 0;
    }
     
    void searchName(char *name,char *nom, FILE *listePresences, FILE* listeMembres)
    {
        int find=0;
        fgets(name, LIM, listeMembres);
        fgets(nom, LIM, listePresences);
     
        while(feof(listeMembres)==0)
        {
            find=0;
            while(feof(listePresences)==0)
            {
                if(strcmp(name,nom)==0)
                {
                    find=1;
                    break;
                }
                fgets(nom, LIM, listePresences);
            }
            if(find==0)
            {
                printf("%s",name);
            }
            rewind(listePresences);
            fgets(name, LIM, listeMembres);
        }
    }
    Encore une fois, merci à tous pour votre aide!

  8. #8
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    De rien. N'oublie pas de marquer la discussion comme résolue et de mettre des à ceux qui t'ont aidé

  9. #9
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut
    J'ai crié victoire trop vite...
    Le programme fonctionne correctement sauf pour le dernier nom dans les présences, le programme semble ne pas le lire...
    Il m'affiche constamment dans la console le nom de la dernière personne... Comme si l'instruction venait trop tôt et que le programme n'avait pas le temps de lire le dernier nom...

    Exemple :
    Liste 1 :

    Astérix
    Obélix
    Idefix
    Panoramix

    Liste 2 :

    Obélix
    Idefix
    Panoramix

    Or la console va m'afficher Astérix (normal) et Panoramix (alors que Pano est présent dans les deux listes...)

  10. #10
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    A vue de nez, je me demande si les noms sont vraiment identiques dans les deux fichiers: n'oublie pas que fgets prend le caractère newline aussi. Donc si tu as un des deux fichiers avec Panoramix\n et l'autre avec Panoramix\eof ça ne donnera pas la même chaîne de caractères.

  11. #11
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut
    En effet, le problème vient de là car dans la première liste, le nom est tout au début, donc associé, je suppose, à un \n. Or dans la deuxième liste, il est tout en dessous, donc avec un \eof...
    Existe-t'il un moyen de contrer ce problème?

  12. #12
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    eh bien vérifier qu'il y a bien une nouvelle ligne à la fin des deux fichiers est une solution (pas très élégante).
    Sinon il faut que tu te plonges un peu plus dans la manipulation des fichiers...
    http://www.cplusplus.com/reference/cstdio/

  13. #13
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2015
    Messages : 59
    Par défaut
    J'ai trouvé une autre façon, vu que ce programme sera pour utilisation personnelle uniquement, je me suis permis d'y aller un peu barbare et ça semble fonctionner...
    J'ai simplement rajouter un "FIN" deux lignes plus bas dans mon deuxième fichier comme ça plus aucun nom dans ma liste de présence ne se fini par un \eof et tout semble fonctionner...

    Comme le dit très bien mon prof de programmation : "Un bon informaticien est un informaticien fainéant mais intelligent"
    Je passe la discussion en résolu et vous remercie tous de m'avoir aidé

  14. #14
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 551
    Par défaut
    Bonsoir
    Citation Envoyé par stendhal666 Voir le message
    Dans ces cas-là, il ne faut pas hésiter à laisser tomber son clavier (au sens figuré, hein?) et à griffonner un peu de pseudo-code. Pour l'instant tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Tant qu'il y a des noms dans la liste de présence:
      Si c'est le nom du membre:
        Alors on prend le prochain membre et on revient au début de la liste de présence
      Sinon:
        On prend le prochain présent et s'il n'y en a plus on affiche le nom du membre
    Donc mettons qu'on soit à la fin de liste de présence et qu'on ait pas trouvé le nom (ligne 6). Que se passe-t-il? On revient au début de la boucle qui nous dit: si je n'ai plus de nom dans la liste de présence, c'est fini. Du coup, eh bien, c'est fini -après le premier nom si le deuxième n'est pas dans la liste de présence.

    Je dirais qu'il te faut plutôt une double boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Tant qu'il y a des membres:
      trouvé = faux
      Tant qu'il y a des présents:
         si membre = présent: alors trouvé = vrai et break
      si trouvé = faux: print membre
      rewind presents
    Je ne suis pas d'accord avec l'algorithme proposé pour la recherche des informations, cela peut très vite prendre un temps long et de plus il est fort possible d'avoir des résultats qui ne correspondent en rien aux attentes souhaitées.
    Citation Envoyé par djesty Voir le message
    J'ai crié victoire trop vite...
    Le programme fonctionne correctement sauf pour le dernier nom dans les présences, le programme semble ne pas le lire...
    Il m'affiche constamment dans la console le nom de la dernière personne... Comme si l'instruction venait trop tôt et que le programme n'avait pas le temps de lire le dernier nom...


    Exemple :
    Liste 1 :

    Astérix
    Obélix
    Idefix
    Panoramix

    Liste 2 :

    Obélix
    Idefix
    Panoramix

    Or la console va m'afficher Astérix (normal) et Panoramix (alors que Pano est présent dans les deux listes...)
    Il est préférable d'avoir une approche logique, simple et si possible robuste.
    Vous comptez faire, une comparaison des éléments d'un fichier avec un autre fichier, c'est-à-dire faire une comparaison lexicale entre deux contenue du fichier afin de trouver l'inconnue. De façon simple l'idéal est d'implémenter et d'utiliser une table de hachage qui a un grand avantage celui de la recherche d'éléments en un temps constant avec cette approche, on est sûr d'établir une liste des absences voir plus par la suite. Le but va donc être de créer une liste de hachage qui sera rempli avec les données de l'un des deux fichiers de l'exemple plus précisément, on va calculer l'empreinte d'un mot du fichier X qui n'est rien d'autre l'indice de la case dans laquelle sera stocké la donnée. Après remplissage de notre table de hachage, il est alors très simple de savoir si le contenu du fichier Y est présent dans le fichier X en comparant juste les indices du fichier Y avec celle de l'indice du fichier X et si l'indice est vide alors la donnée est unique dans le cas contraire si elle existe cas de notre exemple, la personne est considérer comme étant présent.
    Cela donnerait le code source ci-dessous dont certains éléments sont à revoir où ont complété..
    /!\Attention le code source peut comporter des erreurs de programmation.
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
     
    /*
    *  Exemple Recherche de données. Bêta 0.1
    *  File: source.c
    *  Version: 0.0.1 GPL V3.
    *  Created by SAMBIA39 on 28/12/2015.
    *  Copyright (c) 2015 SAMBIA39 & Developpez.net & Xjagercodes.com
    */ 
     
    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
     
    /*
     * Structure des donnée 
     * et gestion des collisions.
     */
    struct s_data{
        char *pData;
        struct s_data *ptr;
    };
     
    /*
     * Pointeur sur tableaux de char 
     * pour les résultats d'inconnue.
     */
    typedef char *pTabRslt[UCHAR_MAX];
     
    /*
     * Pointeur sur tableaux de structure 
     * par définition la table de hachage.
     */
    typedef struct s_data *pData[USHRT_MAX];
     
     
    /*
     * Fonction qui fournit l'id de stockage 
     * des informations grâce à la signature 
     * du texte.
     */
    unsigned short f_id_data( char *src ){
        unsigned int id = 0;
        if( NULL != src ){
            while( '\0' != *src )
                id = ( id * 31 + (unsigned char)*src++ )%USHRT_MAX;
        }
        return id;
    }
     
    /*
     * Fonction qui ajoute les éléments 
     * à leurs indices fournis adéquats.
     */
    void f_add_data( pData data, char *str ){
     
        unsigned short id = 0;
        struct s_data *ptr = NULL;
     
        id = f_id_data( str );
        if( NULL == (ptr = malloc( sizeof(struct s_data)))){
            fprintf( stderr, "(%d)\t%s\n\t:%s\n", errno,
                    "Échec allocation de mémoire", strerror(errno) );
            exit( EXIT_FAILURE );
        }
        ptr->pData = strdup( str );
        ptr->ptr = data[id];
        data[id] = ptr;
    }
     
    /*
     * Fonction qui teste l'existence de la 
     * donnée en comparant les indices si l'indice 
     * pointe sur une cellule vide alors on a une 
     * valeur non répertoriée dans le cas contraire, 
     * elle existe déjà.
     */
    int f_ExistData( pData data, char *cmp ){
     
        struct s_data *ptr = NULL;
        unsigned int id = f_id_data( cmp );
        ptr = data[id];
        for( ptr = data[id]; NULL != ptr; ptr = ptr->ptr ){
            if( 0 == strcmp( ptr->pData, cmp) )
                return 0;
        }
        return 1;
    }
     
    /*
     * Fonction qui charge les éléments 
     * d'un fichier dans la bonne case 
     * de la table de hachage.
     */
    void f_open_and_load_data(pData data, char *psrc ){
     
        errno = 0;
        FILE *pFile = NULL;
        char buffer[UCHAR_MAX];
     
        if( NULL == (pFile = fopen( psrc, "r") ) ){
            fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                    "Erreur open file", strerror(errno) );
            exit( EXIT_FAILURE );
        }
     
        while( NULL != fgets( buffer, UCHAR_MAX, pFile) )
            f_add_data( data, buffer );
     
        fclose( pFile );
        pFile = NULL;
    }
     
    /*
     * Fonction qui affichage les 
     * informations stockées ( Les résultat ).
     */
    void f_print_data( pTabRslt Data ){
        unsigned int i = 0;
        for( i = 0; NULL != Data[i]; i++ )
            fprintf( stdout, "(%d) -> %s\n", i, Data[i] );
    }
     
    /*
     *  Fonction libération des 
     *  mémoires allouées.
     */
    void f_free_all_data( pTabRslt Data ){
     
        unsigned int i = 0;
        for( i = 0; i < UCHAR_MAX; i++ ){
            if( NULL != Data[i] ){
                free( Data[i] );
                Data[i] = NULL;
            }
        }
    }
     
    /*
     * Fonction qui charge sauvegarde 
     * les résultats dans un tableau en utilisant 
     * ou définissant un indice au cas où l'en 
     * souhaiteraient ajouter plus de résultats aux tableaux.
     */
    int f_add_rslt( pTabRslt data, char *buffer, unsigned int offset ){
     
        if( NULL == (data[offset] = malloc( strlen(buffer)+1 * sizeof(char)))){
                f_free_all_data( data );
                fprintf( stderr, "(%d)\t:%s[%d]\n\t:%s\n", errno,
                    "Erreur Allocation mémoire", offset, strerror(errno) );
                return EXIT_FAILURE;
            }
     
            data[offset] = strdup( buffer );
            return EXIT_SUCCESS;
    }
     
    /*
     * Fonction qui compare le contenu 
     * d'un autre fichier avec la table de hachage.
     */
    void f_cmp_info_data( pData data, pTabRslt Data_Rslt, char *src ){
     
        errno = 0;
        FILE *pFile = NULL;
        char buffer[UCHAR_MAX];
        unsigned int offset = 0;
     
        if( NULL == (pFile = fopen( src, "r") ) ){
            fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                    "Erreur open file", strerror(errno) );
            exit( EXIT_FAILURE );
        }
     
        while( NULL != fgets( buffer, UCHAR_MAX, pFile) ){
            if( 0 != f_ExistData( data, buffer) ){
                if( EXIT_FAILURE == f_add_rslt( Data_Rslt, buffer, offset ) )
                    exit( EXIT_FAILURE );
                offset++;
                memset( buffer, 0, UCHAR_MAX );
            }
        }
     
        fclose( pFile );
        pFile = NULL;
     
    }
    /*
     * Fonction debug affichage 
     * des données du tableau de hachage.
     */
    void f_print_data_hash( pData data ){
     
        unsigned int i = 0;
        struct s_data *p = NULL;
        while( USHRT_MAX > i ){
            for( p = data[i]; NULL != p; p = p->ptr ){
                if( NULL == p->pData )
                    fprintf( stdout, "NULL\n" );
                fprintf( stdout, "%s\n", p->pData );
            }
            i++;
        }
    }
     
    /*
     * Fonction debug free
     * des données du tableau de hachage.
     */
    void f_free_data_hsh( pData data ){
     
        // À vous de faire quelque chose.
    }
     
     
    int main( void ){
     
        //Déclaration et initialisation.
        pData Data = { NULL };
        pTabRslt Data_Rslt = { NULL };
     
        //Chargement et comparaison des données.
        f_open_and_load_data( Data, "Text_B.txt" );
        f_cmp_info_data( Data, Data_Rslt, "Text_A.txt" );
     
        //Affichage du résultat.
        fprintf( stdout, "Résultat du traitement....\n" );
        f_print_data( Data_Rslt );
        f_free_all_data( Data_Rslt );
     
        /*
         * /!\ Obligation libération des données 
         * de hachage avant de quitter.
         */
        return EXIT_SUCCESS;
    }

    Code Text_A : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Obélix
    Idefix 
    Panoramix
    Astérix
    sambia39
    www.developpez.net
    www.xjagercodes.com
    Code Text_B : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Obélix
    Idefix 
    Panoramix
    Code ./Out : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Résultat du traitement....
    (0) -> Astérix
     
    (1) -> sambia39
     
    (2) -> www.developpez.net
     
    (3) -> www.xjagercodes.com
    Résultat attendu sans les données ajoutées précédemment à savoir "sambia39, www.developpez.net et www.xjagercodes.com" dans la liste A nous obtenons comme convenu le résultat attendu "Astérix" qui est le suivant.
    Code ./Out : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Résultat du traitement....
    (0) -> Astérix
    À vous de faire le mi num pour complète et adapté l'exemple donné à votre projet.
    à bientôt

  15. #15
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    @sambia39: la table de hachage est une bonne idée mais:
    1) la grande objection c'est qu'on sort de la commande: on ne se contente pas de la lecture des fichiers, on crée une structure de données résidant en mémoire; c'est un trade-off mémoire / temps différent!
    2) pourquoi l'algorithme, certes lent, proposé en pseudo-code pourrait-il donner des résultats faux? Le problème qui s'est posé par la suite vient de l'implémentation, pas du pseudo-code.

  16. #16
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 551
    Par défaut
    Bonjour
    Citation Envoyé par stendhal666 Voir le message
    @sambia39: la table de hachage est une bonne idée mais:
    1) la grande objection c'est qu'on sort de la commande: on ne se contente pas de la lecture des fichiers, on crée une structure de données résidant en mémoire; c'est un trade-off mémoire / temps différent!
    2) pourquoi l'algorithme, certes lent, proposé en pseudo-code pourrait-il donner des résultats faux? Le problème qui s'est posé par la suite vient de l'implémentation, pas du pseudo-code.
    • Je ne vois pas en quoi concrètement nous sortons d'une commande ( je n'ai pas trop compris la notion de commande) de plus vous dite "On ne se contente pas de la lecture des fichiers; on crée une structure de données résidante en mémoire", ce qui est faux, on lis les données puis en les stocke dans une table de hachage à l'indice correspondant à leur signature, le tableau étant chargé, je n'ai plus besoin de travailler avec le fichier X, mais en revanche pour déterminer l'inconnue, j'aurais besoin du fichier Y seulement en lecture, c'est-à-dire les éléments du fichier Y seront lus les unes à la suite des autres et l'on générera la signature de ces éléments qui nous donneront l'indice d'une case du tableau des éléments de X si une signature de Y correspond à emplacement de X alors la donnée en question existe, ce n'est donc pas une inconnue, mais en revanche s'il existe pas on la stocke dans un autre tableau résultat ou ont l'affiche comme etc.. (bon vous semble).
      L'avantage est que l'on ne travaille pas constamment avec le fichier "X" (pas besoin d'un des deux fichiers) deuxièmes points avec la table de hachage, on a un accès en "O(1)" quel que soit le nombre d'éléments dans la table de hachage. Dans le cas où en gérerait, les collisions, c'est-à-dire plusieurs données peuvent se trouver dans une même case, le temps d'accès dans le pire des cas va être de l'ordre d'O(n) mais dans le cas de notre exemple la recherche reste en O(1) un gain de temps énorme. Comme tu le soulignes, il faut de la mémoire du tableau de hachage qui prend de la place, mais en usant d'un compromis à savoir restreindre la signature en fonction de la taille du tableau mais également chaîner les informations en cas de collision nous donne un avantage certain (si je peux le dire) et sur un ordinateur personnel ce n'est pas la mémoire qui nous manque surtout de nos jours sauf si l'on travaille par exemple dans le domaine des systèmes embarqués qui doivent répondre à des contraintes strictes.
    • L'algorithme est assez lent en recherche, c'est un fait là où il est et pas bon réside dans le fait que si dans le deuxième fichier nous avant des doublons à mon avis on afficherait deux fois la même chose pire toutes les données et cela n'est pas dû au fait que l'implémentation du code source soit erronée, mais que l'algorithme en lui-même est totalement mal pensé et mal conçu exemple. nous allons appliquer votre algorithme et le tester sur les données de base et regardant ensemble les résultats.

      Rappel de votre A & B l'algorithme.
      Code Algorithme A : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
       
      Tant qu'il y a des noms dans la liste de présence:
        Si c'est le nom du membre:
          Alors on prend le prochain membre et on revient au début de la liste de présence
        Sinon:
          On prend le prochain présent et s'il n'y en a plus on affiche le nom du membre
      Code Algorithme B : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
       
      Tant qu'il y a des membres:
        trouvé = faux
        Tant qu'il y a des présents:
           si membre = présent: alors trouvé = vrai et break
        si trouvé = faux: print membre
        rewind presents

      Code Liste Texte_A : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
       
      Obélix
      Idefix 
      Panoramix
      Astérix
      Code Liste Texte_B : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
       
      Panoramix
      Obélix
      Idefix 
      Panoramix
      Obélix

    Le code source adapté
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
     
    int main( void ){
     
        FILE *pFile_A = NULL;
        FILE *pFile_B = NULL;
        char buffer_A[UCHAR_MAX];
        char buffer_B[UCHAR_MAX];
     
        if( NULL != ( pFile_A = fopen( "Texte_B.txt", "r") ) ){
            if( NULL == (pFile_B = fopen( "Texte_A.txt", "r") ) ){
                fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                        "Erreur ouverture de fichier", strerror(errno) );
                exit( EXIT_FAILURE );
            }
        }else{
            fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                "Erreur ouverture de fichier", strerror(errno) );
            exit( EXIT_FAILURE );
        }
     
        while( NULL != fgets( buffer_A, UCHAR_MAX, pFile_A) ){
            while( NULL != fgets( buffer_B, UCHAR_MAX, pFile_B ) ){
                if( 0 != strcmp( buffer_A, buffer_B) ){
                    fprintf( stdout, "-> %s\n", buffer_B );
                    break;
                }
            }
            rewind( pFile_B );
        }
     
        fclose( pFile_A );
        fclose( pFile_B );
        pFile_A = pFile_B = NULL;
     
        return EXIT_SUCCESS;
    }

    Code Résultat : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    -> Obélix
     
    -> Idefix 
     
    -> Obélix
     
    -> Obélix
     
    -> Idefix 
     
    -> Obélix
    Conclusion des valeurs correctes, mais en doublon pire erroné et cela ne répond en rien aux tentes souhaitées. Si vous souhaitez faire, d'autres testent amusées vous a modifié la liste ou le code source, il subsistera à mon avis toujours des d'anomalie.
    voilà pourquoi pour certaines de ces raisons, j'estime que l'algorithme n'est pas correct peut-être que je me trompe si c'est, le cas pourriez-vous me donner votre point de vue ?
    à bientôt.

  17. #17
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    @sambia34

    Bon, ce n'est pas grave d'être un peu désagréable mais autant être exact:
    - la commande, c'est ce qu'a demandé celui qui posait la question; et celui qui posait la question voulait comparer deux fichiers sans mettre un fichier en mémoire (ce qui aurait pourtant été une bonne idée, raison pour laquelle j'approuvais la table de hachage).
    - mon algorithme ce n'est pas un A et un B mais juste le B. Le A c'est ce que faisait djesty, le B ce que je lui conseillais de faire.
    - mon algorithme n'est pas ce que vous avez traduit en C. Une traduction de cet algorithme B que je proposais serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        while( NULL != fgets( buffer_A, UCHAR_MAX, pFile_A) ){ // correspond à la ligne 27 de l'implémentation que vous proposez
            trouve = 0;
            while( NULL != fgets( buffer_B, UCHAR_MAX, pFile_B ) ){
                if( 0 == strcmp( buffer_A, buffer_B) ){
                    trouve = 1;
                    break;
                }
            }
     	if (!trouve) fprintf( stdout, "-> %s\n", buffer_B );
            rewind( pFile_B );
        }
    et il marche parfaitement.
    - mettre sur la liste des présents ou la liste des membres comme vous le faites des doublons ne me paraît pas très intéressant.

    Donc mon conseil, critiquez à meilleur escient, surtout si vous montez sur vos grands chevaux.

  18. #18
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 551
    Par défaut
    Bonsoir
    Attention, je n'ai pas critiqué, j'ai bien mentionné que je ne suis pas d'accord avec l'algorithme pour les raisons suivantes en gras:
    • Je ne suis pas d'accord avec l'algorithme proposé pour la recherche des informations, cela peut très vite prendre un temps long et de plus il est fort possible d'avoir des résultats qui ne correspondent en rien aux attentes souhaitées.
    • L'algorithme est assez lent en recherche, c'est un fait là où il est pas bon réside dans le fait que si dans le deuxième fichier nous avant des doublons à mon avis on afficherait deux fois la même chose pire toutes les données et cela n'est pas dû au fait que l'implémentation du code source soit erronée, mais que l'algorithme en lui-même est totalement mal pensé et mal conçu

    De, plus le résultat attendu doit être un seul affichage, ceux qui est logiques (donc pas de doublons), car si l'on obtient des doublons, c'est que quelque part nous ne gérant pas bien une ou certaines conditions, ce qui est très nettement différent de notre attente, "doit-on afficher plus d'une fois l'unique et seul inconnu ? " Personnellement je ne pense pas.
    Deuxième point, je ne charge pas le fichier en mémoire, je charge le contenu du fichier. Vous avez également pris la peine de corriger mon code source fondé sur le second algorithme, c'est très bien et vous dit que les doublons ne vous paraissent pas très intéressants. Or il faut prendre cette variante en considération exemple
    Code Texte_A : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Obélix
    Idefix 
    Panoramix
    Astérix
    Code Texte_B : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Idefix
    Panoramix
    Panoramix
    Idefix
    Panoramix
    Panoramix
    Idefix
    Code source modifier et ajouts de doublons
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
     
    int main( void ){
     
        FILE *pFile_A = NULL;
        FILE *pFile_B = NULL;
        char buffer_A[UCHAR_MAX];
        char buffer_B[UCHAR_MAX];
        int trouve = 0;
     
        //Teste A
        if( NULL != ( pFile_A = fopen( "Texte_B.txt", "r") ) ){
            if( NULL == (pFile_B = fopen( "Texte_A.txt", "r") ) ){
                fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                        "Erreur ouverture de fichier", strerror(errno) );
                exit( EXIT_FAILURE );
            }
        }else{
            fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                "Erreur ouverture de fichier", strerror(errno) );
            exit( EXIT_FAILURE );
        }
     
        fprintf( stdout, "Teste 1\n" );
        while( NULL != fgets( buffer_A, UCHAR_MAX, pFile_A) ){ 
            // correspond à la ligne 27 de l'implémentation que vous proposez
            trouve = 0;
            while( NULL != fgets( buffer_B, UCHAR_MAX, pFile_B ) ){
                if( 0 == strcmp( buffer_A, buffer_B) ){
                    trouve = 1;
                    break;
                }
            }
     	if (!trouve) fprintf( stdout, "-> %s\n", buffer_B );
            rewind( pFile_B );
        }
     
     
        fclose( pFile_A );
        fclose( pFile_B );
        pFile_A = pFile_B = NULL;
     
        //Teste B
        if( NULL != ( pFile_A = fopen( "Texte_A.txt", "r") ) ){
            if( NULL == (pFile_B = fopen( "Texte_B.txt", "r") ) ){
                fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                        "Erreur ouverture de fichier", strerror(errno) );
                exit( EXIT_FAILURE );
            }
        }else{
            fprintf( stderr, "(%d)\t:%s\n\t:%s\n", errno,
                "Erreur ouverture de fichier", strerror(errno) );
            exit( EXIT_FAILURE );
        }
     
        fprintf( stdout, "Teste 2\n" );
        while( NULL != fgets( buffer_A, UCHAR_MAX, pFile_A) ){ 
            // correspond à la ligne 27 de l'implémentation que vous proposez
            trouve = 0;
            while( NULL != fgets( buffer_B, UCHAR_MAX, pFile_B ) ){
                if( 0 == strcmp( buffer_A, buffer_B) ){
                    trouve = 1;
                    break;
                }
            }
     	if (!trouve) fprintf( stdout, "-> %s\n", buffer_B );
            rewind( pFile_B );
        }
     
     
        fclose( pFile_A );
        fclose( pFile_B );
        pFile_A = pFile_B = NULL;
     
        return EXIT_SUCCESS;
    }
    Code Resultat : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Teste 1
    -> Astérix
     
    -> Astérix
     
    -> Astérix
     
    Teste 2
    -> Idefix
    -> Idefix
    -> Idefix

    À votre avis dans les deux cas où l'un des deux cas, vous obtenez un résultat correct ?
    Comme dit pasteur "Ayez le culte de l'esprit critique."
    sambia39 != sambia34
    à bientôt

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 14/05/2015, 11h41
  2. comparaison valeurs entre deux fichiers texte
    Par seb-65 dans le forum Langage
    Réponses: 8
    Dernier message: 18/12/2013, 14h46
  3. [XL-2010] Comparaison de formule entre deux fichiers excel
    Par africanism95 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 05/04/2013, 16h59
  4. [Débutant] Comparaisons entre deux fichiers textes
    Par shootgirl dans le forum MATLAB
    Réponses: 9
    Dernier message: 27/09/2011, 15h50
  5. Réponses: 22
    Dernier message: 25/02/2009, 10h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo