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 :

quelques questions importantes


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Par défaut quelques questions importantes
    Bonjour,

    1) La compilation se passe bien. Mais, l'exécution ne se termine pas correctement et il y apparaition d'une fenêtre qui affiche:
    <couleur nom="rouge">Debug assertion Failed!
    Program :
    File :f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
    Expression : _CrtIsValidHeapPointer(pUserData)
    Line : 1317
    </couleur>
    Que signifie ce message ?

    2)
    Est ce que realloc()peut conduire dans certains cas à une fuite mémoire.
    Quand on utilise malloc() et realloc() ?

    Quels sont les tests à ajouter au programme pour assurer que nous avons bien alloués de la mémoire, que nous avons bien libérer les espaces mémoires utilisées, que les fichiers utilisés sont bien ouverts et fermants, que les chaines e caractères passées comme paramètres sont valides etc... ?

    3)

    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
    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
     
    char * mstrndup(const char *str, size_t n)
    {
        char *ret = malloc((n+1) * sizeof(char));
    if (ret == NULL)
    perror("erreur d'allocation\n");
        if(!ret)
            exit(0xDEAD);
     
        strncpy(ret, str, n);
        ret[n] = 0;
        return ret;
    }
     
    void display_tab(char** tab)
    {
      while (tab && *tab)
      {
     
       printf("%s\n", *tab);
     
       tab++;
     
      } 
    }
     
    void free_table(char** t)
     
    {
     
      char** head = t;
     
     
     
      while (t && *t)
     
      {
     
        free(*t);
     
        t++;
     
     
     
      }
     
      free(head);
     
    }
     
     
     
    char** copy_tab(char** tab)
     
    {
     
      char** res = NULL;
     
      int nb = 0;
     
     
     
      while (tab && *tab)
     
      {
     
        nb++;
     
        res = realloc(res, (nb + 1) * sizeof (char*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
        res[nb - 1] = mstrndup(*tab, strlen(*tab));
     
        res[nb] = 0;
     
        tab++;
     
      }
     
     
     
      return res;
     
    }
     
    void free_tab(char **t, size_t len)
    {
        if(t)
        {
            size_t i;
            for(i = 0; i < len; i++)
                free(t[i]);
            free(t);
        }
    }
    J'ai pris quelques fonctions de mon programme:

    - char * mstrndup(const char *str, size_t n)
    - void display_tab(char** tab)
    - char** copy_tab(char** tab)
    - void free_table(char** t)
    - void free_tab(char **t, size_t len)

    avec:
    t: c'est un pointeur sur le tableau(tableau de chaine de carctères).
    *t: c'est la case en cours du tableau
    **t: c'est la valeur

    Je voulais vérifier avec vous si les fonctions décrites au dessus sont bien faites. Est ce que il y a des tests à ajouter et à vérifier concernant l'allocation, la taille de chaines, les paramètres des fonctions, etc...?

    Merci.

  2. #2
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par vivaviva Voir le message
    1) La compilation se passe bien. Mais, l'exécution ne se termine pas correctement et il y apparaition d'une fenêtre qui affiche:
    <couleur nom="rouge">Debug assertion Failed!
    Program :
    File :f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
    Expression : _CrtIsValidHeapPointer(pUserData)
    Line : 1317
    </couleur>
    Que signifie ce message ?
    A priori que tu as corrompu quelque part la mémoire.

    Citation Envoyé par vivaviva Voir le message
    Est ce que realloc()peut conduire dans certains cas à une fuite mémoire.
    Quand on utilise malloc() et realloc() ?
    Mal utilisé oui.
    Par exemple, si l'allocation échoue, realloc() retourne NULL or lorsque la même variable est utilisé pour contenir l'adresse passé à realloc et celle de retour, on perd dans ce cas l'adresse initiale et on ne peut donc pas libérer la mémoire correspondante.

    Réfères toi au lien que je t'ai fourni dans un sujet précédent, tu auras davantage d'explications.

    Citation Envoyé par vivaviva Voir le message
    Quels sont les tests à ajouter au programme pour assurer que nous avons bien alloués de la mémoire, que nous avons bien libérer les espaces mémoires utilisées, que les fichiers utilisés sont bien ouverts et fermants, que les chaines e caractères passées comme paramètres sont valides etc... ?
    Dans le code, à part vérifier les valeurs de retours des différentes fonctions et éventuellement les paramètres passées aux tiennes et de réagir correctement en libérant ce qui est nécessaire, il n'y a pas grand chose d'autre à faire.

    Par contre il existe différents outils qui peuvent t'aider à découvrir des problèmes : splint, valgring, etc. Le premier étant bien entendu un compilateur correctement réglé avec un niveau élevé de warning.

    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    char * mstrndup(const char *str, size_t n)
    {
       char *ret = malloc((n+1) * sizeof(char));
       if (ret == NULL)
          perror("erreur d'allocation\n");
       if(!ret)
          exit(0xDEAD);
     
       strncpy(ret, str, n);
       ret[n] = 0;
       return ret;
    }
    • Il est assez surprenant de mettre deux tests (qui plus est dans deux styles différents) pour tester le retour de malloc.
    • Plutôt que sizeof(char), je mettrais sizeof(*ret), ce qui permet des évolutions plus simples (même si dans une fonction du style de celle-ci ça ne devrait pas poser trop de problèmes).
    • 0xDEAD n'est pas une valeur de retour portable d'un programme. Les seules valeurs normalisée sont 0, EXIT_SUCCESS et EXIT_FAILURE.
    • A priori, ce n'est pas à une fonction aussi bas niveau que celle-ci d'afficher l'erreur et de prendre la décision d'arrêter le programme. Elle devrait plutôt signaler l'erreur (en retournant NULL) et laisser à l'appelant le soin de traiter l'erreur ou de la propager à son tour à une fonction de plus haut niveau. Dans le cas d'un petit programme d'apprentissage ce n'est pas grave, mais pour la réutilisabilité de la fonction, cela peut devenir important.


    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void display_tab(char** tab)
    {
       while (tab && *tab)
       {
          printf("%s\n", *tab);
          tab++;
       } 
    }
    • Il manque des const dans le prototype de la fonction.


    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void free_table(char** t)
    {
       char** head = t;
     
       while (t && *t)
       {
          free(*t);
          t++;
       }
       free(head);
    }
    Pas de remarque particulière.

    Citation Envoyé par vivaviva Voir le message
    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
     
    char** copy_tab(char** tab)
    {
       char** res = NULL;
       int nb = 0;
     
       while (tab && *tab)
       {
          nb++;
          res = realloc(res, (nb + 1) * sizeof (char*));
          if (res == NULL)
             perror("erreur d'allocation\n");
     
          res[nb - 1] = mstrndup(*tab, strlen(*tab));
          res[nb] = 0;
          tab++;
       }
     
       return res;
    }
    • Il manque des const dans le prototype de la fonction.
    • sizeof(*res) plutôt que sizeof(char*)
    • Est-ce vraiment à cette fonction d'afficher un message en cas d'erreur du realloc() ? Ne devrait-elle pas plutôt signalé l'erreur à une fonction de plus haut niveau ?
    • Si realloc() échoue, l'adresse préalblement contenue dans res est perdue, tu as une fuite mémoire.
    • Si realloc() échoue, res vaut NULL, tu affiches bien un message d'erreur mais tu continues à l'utiliser.


    Sinon, juste une petite remarque sur la méthode utilisée : il n'est pas très efficace de réallouer à chaque tour de boucle, il serait plus efficace de compter dans un premier temps la taille de tab, d'allouer ce dont tu as besoin puis de remplir.
    Tu peux même te passer de recompter le nombre d'éléments de tab en le passant en paramètre de la fonction, voire en créant une structure contenant le tableau et le nombre d'élément est en passant un pointeur sur cette structure plutôt que le tableau à toutes tes fonctions.

    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void free_tab(char **t, size_t len)
    {
       if(t)
       {
          size_t i;
          for(i = 0; i < len; i++)
             free(t[i]);
          free(t);
       }
    }
    Pas de remarque particulière

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Petites remarques perso à rajouter aux remarques de gl
    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void display_tab(char** tab)
    {
      while (tab && *tab)
      {
       printf("%s\n", *tab);
       tab++;
      } 
    }
    Le test sur tab est inutile. A priori, si on appelle cette fonction, on lui passera un pointeur correct.
    Toutefois, on peut imaginer que cette fonction pourra être appelée avec un pointeur NULL (ce qui est d'ailleurs prévu pour free). Dans ce cas, il est dommage de refaire le test à chaque itération. Je proposerais alors la fonction suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void display_tab(char** tab)
    {
       if (tab == NULL) return;
       for (;*tab; tab++)
      {
       printf("%s\n", *tab);
      } 
    }
    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void free_table(char** t)
    {
      char** head = t;
      while (t && *t)
      {
        free(*t);
        t++;
      }
      free(head);
    }
    Même remarque que ci-dessus. J'ajouterais en plus qu'il est dommage de mémoriser la valeur passée en paramètre dans une mémoire invariante et de faire varier le paramètre. Perso, j'aurais fait le contraire => fait varier la variable locale et laissé le paramètre inchangé. Ca ne change rien au résultat mais c'est conceptuellement plus naturel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void free_table(char** t)
    {
      char** head;
     
      if (t == NULL) return;
     
      for (head=t; *head; head++)
        free(*head);
     
      free(t);
    }
    Citation Envoyé par vivaviva Voir le message
    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
    char** copy_tab(char** tab)
    {
      char** res = NULL;
      int nb = 0;
     
      while (tab && *tab)
      {
        nb++;
        res = realloc(res, (nb + 1) * sizeof (char*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
        res[nb - 1] = mstrndup(*tab, strlen(*tab));
        res[nb] = 0;
        tab++;
      }
      return res;
    }
    Attention => si le realloc se passe mal, res contient NULL mais on a perdu la zone précédente (qui reste allouée).
    Généralement, on fait du realloc dans un autre pointeur, et si le realloc s'est bien passé, on le recopie dans le pointeur d'origine. Dans le cas contraire, on a toujours le pointeur d'origine pour libérer la zone allouée.
    De plus, c'est dommage d'appeler une fonction aussi lourde que realloc pour 1 élément en plus. Généralement, quand on a un tableau grossissant, on lui alloue et réalloue des blocs de "N" éléments. Et on gère un compteur interne pour remplir les éléments alloués disponibles jusqu'à ce qu'on atteigne la taille allouée dans ce cas on réalloue N éléments de plus.

    Citation Envoyé par vivaviva Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void free_tab(char **t, size_t len)
    {
        if(t)
        {
            size_t i;
            for(i = 0; i < len; i++)
                free(t[i]);
            free(t);
        }
    }
    Dommage. Utiliser t[i] à chaque itération est plus long que d'avoir un pointeur directement placé là où il faut (comme pour la fonction free_table)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void free_tab(char **t, size_t len)
    {
        size_t i;
        char **pt;
     
        if(t == NULL) return:
     
        for(i = 0, pt=t; i < len; i++, pt++)
           free(*pt);
        free(t);
    }
    Remarque générale: j'ai l'habitude de faire mes tests au préalable à tout traitement et sortir si le contrôle n'est pas correct. Et ensuite, une fois arrivé au bloc de travail, ce traitement commence en début de ligne et j'ai encore tout l'écran pour programmer mon algo.
    Exemple
    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
    fonction()
    {
        if (not condition 1)
        {
            printf("condition 1 non remplie\n");
            return 1;
        }
     
        if (not condition 2)
        {
            printf("condition 2 non remplie\n");
            return 2;
        }
     
        if (not condition 3)
        {
            printf("condition 3 non remplie\n");
            return 3;
        }
     
        travail
        return 0;
    }
    Je ne suis pas seul à utiliser cette façon de faire mais certains autres programmeurs préfèrent une écriture plus académique, style
    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
    fonction()
    {
        error=0
        if (condition 1)
        {
            if (condition2)
            {
                 if (condition3)
                 {
                      travail
                 }
                 else
                 {
                      printf("condition 3 non remplie\n");
                      error=3;
                 }
            }
            else
            {
                printf("condition 2 non remplie\n");
                error=2;
            }
        }
        else
        {
            printf("condition 1 non remplie\n");
            error=1;
        }
        return error;
    }
    Les 2 façons d'écrire ont des avantages et des inconvénients (dans la mienne, si la condition 2 ou 3 n'est pas remplie, faut que je libère les ressources éventuelles de la condition 1 avant de sortir donc redondance de code). Donc ce sera à toi de choisir la façon d'écrire dans laquelle tu te sens le mieux.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre éclairé
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Par défaut
    Bonjour,

    Mon problème consiste à identifier la différence et donc faire une comparaison à chaque fois entre deux fichiers:
    -comparaison entre "f.txt" et "f1.txt"
    -comparaison entre "f.txt" et "f2.txt"
    -comparaison entre "f.txt" et "f3.txt"

    On stocke à chaque fois le résultat de comparaison et puis on cherche l'intersection entre ces trois résultats de comparaison.

    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
    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
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
     
    #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 == NULL)
    perror("erreur d'allocation\n");
    	if (t2 == NULL)
    perror("erreur d'allocation\n");
     
        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;
    }
     
     
    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*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
    	res[nb - 1] = mstrndup(s, strlen(s) - 1); /* Get rid of the \n */
     
    	res[nb] = 0;
     
          }
     
        }
     
        fclose(f);
     
        fclose(f1);
     
      }
     
      return res;
     
    }
     
    void display_tab(char** tab)
    {
      while (tab && *tab)
      {
     
       printf("%s\n", *tab);
     
       tab++;
     
      } 
    }
     
    void free_table(char** t)
     
    {
     
      char** head = t;
     
     
     
      while (t && *t)
     
      {
     
        free(*t);
     
        t++;
     
     
     
      }
     
      free(head);
     
    }
     
     
     
    char** copy_tab(char** tab)
     
    {
     
      char** res = NULL;
     
      int nb = 0;
     
     
     
      while (tab && *tab)
     
      {
     
        nb++;
     
        res = realloc(res, (nb + 1) * sizeof (char*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
        res[nb - 1] = mstrndup(*tab, strlen(*tab));
     
        res[nb] = 0;
     
        tab++;
     
      }
     
     
     
      return res;
     
    }
     
    int is_in_tab(char *str, char **tab2)
    {
     while(tab2 &&*tab2)
      {
       if(!strcmp(str,*tab2))
    	   return 1;
      tab2++;	  
      }
     return 0;
    }
     
     
    char** compute_intersect(char** tab1, char** tab2)
     
    {
     
       char** inter = NULL;
     
       int nb = 0; // Nombre d'élément trouvé
     
     
     
      if (!tab2)
     
        return NULL;
     
     
     
      if (!tab1)
     
        return copy_tab(tab2);
     
     
     
      // Ici finir de coder l'intersection
     
      while(tab1 &&*tab1)
     
      {
     
       if(is_in_tab(*tab1,tab2))
     
       {
     
         nb++;// Ici dire que le nb d'élément trouvé est incrémenté de 1
     
         inter = realloc(inter, (nb + 1) * sizeof (char*));// On augmente la taille de inter, de 1
    if (inter == NULL)
    perror("erreur d'allocation\n");
     
    	 inter[nb - 1] = mstrndup(*tab1, strlen(*tab1));// On copie la chaîne trouvé dans inter
     
        inter[nb] = 0; // On met un 0 terminal
     
       }
     
       tab1++;
     
      }
     
      // On pense ensuite à libérer l'ancien tableau de résultat.
     
     free_table(tab1);
    //free_tab(tab1,strlen(tab1));
     return inter; // Enfin on retourne le résultat final.
     
    }
     
    int main(void)
    {
     
      char** res = NULL;
     
     char** intersect = NULL;
     
    	char input[32];
     
      int i;
     
      for (i = 1; i <= 3; i++)
     
      {
     
        sprintf(input,"f%d.txt",i);
     
        res = compare_file("f.txt",input);
     
     
        printf("Comparing f.txt and %s:\n", input);
     
        display_tab(res);
    intersect = compute_intersect(intersect, res);
     
     
        free_table(res);
    	//free_tab(res,strlen(*res));
     
      }
     
     printf("Final result:\n");
      if (intersect == NULL)
    	  perror("erreur\n");
     
      display_tab(intersect);
     
      free_table(intersect);
        return 0;
    }
    La compilation se passe bien. Mais, l'exécution ne se termine pas correctement et il y apparition d'une fenêtre qui affiche:
    <couleur nom="rouge">Debug assertion Failed!
    Program :
    File :f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
    Expression : _CrtIsValidHeapPointer(pUserData)
    Line : 1317
    </couleur>

    l'exécution m'affiche une partie de résultat avant l'apparition de fenêtre.
    elle m'affiche:
    Comparing f.txt and f1.txt:
    b d
    c d
    a b d
    b c d
    a c d
    a b c d
    Comparing f.txt and f2.txt:
    b d
    a b d
    b c d
    a c d
    a b c d
    mais, le résultat souhaité est :
    Comparing f.txt and f1.txt:
    b d
    c d
    a b d
    b c d
    a c d
    a b c d
    Comparing f.txt and f2.txt:
    b d
    a b d
    b c d
    a c d
    a b c d
    Comparing f.txt and f3.txt:
    b d
    c d
    a b d
    b c d
    a c d
    a b c d
    Final result:
    b d
    a b d
    b c d
    a c d
    a b c d
    J'ai remarqué que avant d'arriver à la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    intersect = compute_intersect(intersect, res);
    C'est à lorsque je mis cette fonction en commentaire alors j'obtiens:
    Comparing f.txt and f1.txt:
    b d
    c d
    a b d
    b c d
    a c d
    a b c d
    Comparing f.txt and f2.txt:
    b d
    a b d
    b c d
    a c d
    a b c d
    Comparing f.txt and f3.txt:
    b d
    c d
    a b d
    b c d
    a c d
    a b c d
    C'est bon ceci.

    Mais il me reste cette partie:
    Final result:
    b d
    a b d
    b c d
    a c d
    a b c d
    Comment noua allons modifier ce programme pour obtenir le résultat final ?

    Merci.

  5. #5
    Membre éclairé
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Par défaut
    De plus, le programme au dessus vous avez besoin des fichiers textes suivantes car nous allons besoin de ces fichiers dans le programme :

    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

    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 serais très contente pour vos aides.

    Merci.

  6. #6
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Dommage. Utiliser t[i] à chaque itération est plus long que d'avoir un pointeur directement placé là où il faut (comme pour la fonction free_table)
    En es-tu vraiment aussi sur que ça ? As-tu fait des tests à ce sujet ?

    Avec un compilateur décent et des options de compilation adéquates, il est fort probable que le code généré soit globalement le même dans les deux cas.

  7. #7
    Membre éclairé
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Par défaut
    Bonjour,

    Voici ma nouvelle version. J'ai la testé et çà marche.

    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
    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
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
     
    #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 == NULL)
    perror("erreur d'allocation\n");
    	if (t2 == NULL)
    perror("erreur d'allocation\n");
     
        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;
    }
     
     
    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*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
    	res[nb - 1] = mstrndup(s, strlen(s) - 1); /* Get rid of the \n */
     
    	res[nb] = 0;
     
          }
     
        }
     
        fclose(f);
     
        fclose(f1);
     
      }
     
      return res;
     
    }
     
    void display_tab(char** tab)
    {
      while (tab && *tab)
      {
     
       printf("%s\n", *tab);
     
       tab++;
     
      } 
    }
     
    void free_table(char** t)
     
    {
     
      char** head = t;
     
     
     
      while (t && *t)
     
      {
     
        free(*t);
     
        t++;
     
     
     
      }
     
      free(head);
     
    }
     
     
     
    char** copy_tab(char** tab)
     
    {
     
      char** res = NULL;
     
      int nb = 0;
     
     
     
      while (tab && *tab)
     
      {
     
        nb++;
     
        res = realloc(res, (nb + 1) * sizeof (char*));
    	if (res == NULL)
    perror("erreur d'allocation\n");
     
        res[nb - 1] = mstrndup(*tab, strlen(*tab));
     
        res[nb] = 0;
     
        tab++;
     
      }
     
     
     
      return res;
     
    }
     
    int is_in_tab(char *str, char **tab2)
    {
     while(tab2 &&*tab2)
      {
       if(!strcmp(str,*tab2))
    	   return 1;
      tab2++;	  
      }
     return 0;
    }
     
     
    char** compute_intersect(char** tab1, char** tab2)
     
    {
     
       char** inter = NULL;
       char** tmp_tab1 = tab1;
       int nb = 0; // Nombre d'élément trouvé
     
     
     
      if (!tab2)
     
        return NULL;
     
     
     
      if (!tab1)
     
        return copy_tab(tab2);
     
     
     
      // Ici finir de coder l'intersection
     
      while(tab1 &&*tab1)
     
      {
     
       if(is_in_tab(*tab1,tab2))
     
       {
     
         nb++;// Ici dire que le nb d'élément trouvé est incrémenté de 1
     
         inter = realloc(inter, (nb + 1) * sizeof (char*));// On augmente la taille de inter, de 1
    if (inter == NULL)
    perror("erreur d'allocation\n");
     
    	 inter[nb - 1] = mstrndup(*tab1, strlen(*tab1));// On copie la chaîne trouvé dans inter
     
        inter[nb] = 0; // On met un 0 terminal
     
       }
     
       tab1++;
     
      }
     
      // On pense ensuite à libérer l'ancien tableau de résultat.
     
     free_table(tmp_tab1);
    //free_tab(tab1,strlen(tab1));
     return inter; // Enfin on retourne le résultat final.
     
    }
     
    int main(void)
    {
     
      char** res = NULL;
     
     char** intersect = NULL;
     
    	char input[32];
     
      int i;
     
      for (i = 1; i <= 3; i++)
     
      {
     
        sprintf(input,"f%d.txt",i);
     
        res = compare_file("f.txt",input);
     
     
        printf("Comparing f.txt and %s:\n", input);
     
        display_tab(res);
    intersect = compute_intersect(intersect, res);
     
     
        free_table(res);
    	//free_tab(res,strlen(*res));
     
      }
     
     printf("Final result:\n");
      if (intersect == NULL)
    	  perror("erreur\n");
     
      display_tab(intersect);
     
      free_table(intersect);
        return 0;
    }
    Est ce que on peut améliorer cette solution de sorte que le temps d'exécution soit inférieur ? et Est ce que tous les cas sont prévus par exemple d'allocation et libération de mémoire , pas autres tests à faire etc..?

    Si il y a autre proposition d'autre solution mieux alors c'est intéressant.

    Merci.

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gl Voir le message
    En es-tu vraiment aussi sur que ça ?
    Peut-on être vraiment toujours sûr de ce qu'on dit, quand ce qui est dit est souvent dicté par une espèce de connaissance générale venue de diverses informations lues durant une carrière faite dans l'informatique ???

    Citation Envoyé par gl Voir le message
    As-tu fait des tests à ce sujet ?
    Pas récemment.

    Citation Envoyé par gl Voir le message
    Avec un compilateur décent et des options de compilation adéquates, il est fort probable que le code généré soit globalement le même dans les deux cas.
    Hum... tu me donnes du "probable" pour répondre à une remarque issue de ce qui est écrit à propos de l'arithmétique des pointeurs dans le K&R. T'as tout à fait le droit d'espérer que le compilo fera à ta place une optimisation que tu peux faire toi-même. Mais c'est hasardeux...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    T'as tout à fait le droit d'espérer que le compilo fera à ta place une optimisation que tu peux faire toi-même. Mais c'est hasardeux...
    Ca ressemble quand même beaucoup à de l'optimisation prématurée.

    Un compilateur un tant soi peu efficace va faire cette optimisation. Même en supposant qu'elle ne soit pas faite, le gain unitaire est infime et au prix d'une écriture qui bien que naturelle pour la plupart des développeurs (elle ne me gêne pas du tout et je suis très loin d'être un cas isolé) semble en déstabiliser certains.

    Pour une fonction fortement sollicitée ou qui s'avère être un goulot d'étranglement, oui il faut probablement essayer cette optimisation manuelle.
    Dans les autres cas, je ne suis pas certain que ce soit indispensable.

    A choisir, s'il est nécessaire d'optimiser le code cité dans le message initiale, je chercherais plutôt à réduire le nombre de blocs alloués (par exemple en utilisant un tableau unique) ou le nombre d'appel à realloc().

Discussions similaires

  1. Quelques questions importantes
    Par zikyoubi dans le forum Développement Web en Java
    Réponses: 7
    Dernier message: 02/10/2013, 11h53
  2. Quelques questions + ou - importantes
    Par diaruga dans le forum Débuter
    Réponses: 9
    Dernier message: 04/06/2008, 20h31
  3. [install]Install sous windows... quelques questions
    Par omega dans le forum Eclipse Java
    Réponses: 5
    Dernier message: 26/02/2004, 09h50
  4. [MFC] Quelques questions de débutant...
    Par Sephi dans le forum MFC
    Réponses: 4
    Dernier message: 20/02/2004, 17h25
  5. Quelques questions sur le TWebBrowser...
    Par CorO dans le forum Web & réseau
    Réponses: 3
    Dernier message: 17/01/2003, 21h23

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