tri d'un tableau de struct

Version imprimable

Voir 40 message(s) de cette discussion en une page
Page 2 sur 3 PremièrePremière 123 DernièreDernière
donc c'est comme "une variable unsigned" bien sur si je peux dire ?
Citation:

Envoyé par Médinoc Voir le message
La fonction qsort() exige que la fonction de comparaison prenne ce type de pointeur en paramètre.

pourriez vous me donné quelque condition en programmation la ou je doit use ce pointeur
Citation:

Envoyé par Médinoc Voir le message
  • sizeof tab / sizeof *tab, quand on l'emploie directement sur un tableau (ne pas utiliser sur un pointeur), donne la taille exacte du tableau complet.
    Ici, cette taille est 4. Mais vu que tu ne remplis que les trois premiers éléments du tableau (de 0 à 2 inclus), ça fausse les choses.

  • oups j'ai pas fait attention :ccool: :ccool:Médinoc
  • 07/09/2009, 10h21
    Emmanuel Delahaye
    Citation:

    Envoyé par Echap Voir le message
    donc c'est comme "une variable unsigned" bien sur si je peux dire ?

    aucun rapport. void * définit un pointeur dont on ne connait que la valeur (l'adresse de la variable), mais pas le type pointé (le type de la variable).

    Citation:

    pourriez vous me donné quelque condition en programmation la ou je doit use ce pointeur
    Tu en as un exemple ici avec la fonction de comparaison de qsort() et de bsearch(). C'est utilisé principalement en programmation 'générique', c'est à dire quand on code des comportements indépendant du type de donnée.
  • 07/09/2009, 10h33
    Médinoc
    Citation:

    donc c'est comme "une variable unsigned" bien sur si je peux dire ?
    Non. Le mot-clé unsigned qualifie un type entier. Si c'est l'usage de unsigned tout seul qui te trouble, un petit rappel:

    Si tu écris:
    Code:

    unsigned a;
    Le vrai type de a sera en réalité unsigned int.
  • 07/09/2009, 10h40
    Echap
    Citation:

    Envoyé par Emmanuel Delahaye Voir le message
    aucun rapport. void * définit un pointeur dont on ne connait que la valeur (l'adresse de la variable), mais pas le type pointé (le type de la variable).

    donc il peux pointé sur n'importe quel type de données et on n'est pas obligé définir le type ! c'est bien ça :D
    Citation:

    Envoyé par Emmanuel Delahaye Voir le message
    Tu en as un exemple ici avec la fonction de comparaison de qsort() et de bsearch(). C'est utilisé principalement en programmation 'générique', c'est à dire quand on code des comportements indépendant du type de donnée.

    merçi pour les informations
    mais ce que j'arrive pas a comprendre est ce que qsort() tri l'affichage ou quoi ? car il y a des const
    Code:

    int CompareCitoyenParDate (const void *pcvA, const void *pcvB)
    aussi
    Code:

    static void aff (CIT const *a, size_t n)
    peux etre je suis entrain de dire n'importe quoi :oops: mais je doit le prononcé pour finir avec les fausse méthode de pensé
  • 07/09/2009, 10h58
    Echap
    Citation:

    Envoyé par Médinoc Voir le message
    Non. Le mot-clé unsigned qualifie un type entier. Si c'est l'usage de unsigned tout seul qui te trouble, un petit rappel:

    Si tu écris:
    Code:

    unsigned a;
    Le vrai type de a sera en réalité unsigned int.

    emmm maintenant je comprend :merci:
  • 07/09/2009, 11h07
    Emmanuel Delahaye
    Citation:

    Envoyé par Echap Voir le message
    donc il peux pointé sur n'importe quel type de données et on n'est pas obligé définir le type ! c'est bien ça

    Oui. C'est bien le cas de la fonction générique de tri de tableau qu'st qsort().

    Citation:

    merçi pour les informations
    mais ce que j'arrive pas a comprendre est ce que qsort() tri l'affichage ou quoi ? car il y a des const
    qsort() trie le tableau. Pour trier, il doit à un moment précis de son algorithme, effectuer une comparaison entre les éléments pour savoir si il doit déplacer ou non le ou les éléments (tu n'a jamais écrit d'algo de tri toi même ? Tu devrais, c'est instructif). C'est à ce moment qu'il appelle la fonction utilisateur de comparaison, en lui passant l'adresse des deux éléments. Il attend en retour une valeur 0 (egal) <0 (inférieure) ou > 0 (supérieure) pour agir en conséquence...

    Citation:

    Code:

    int CompareCitoyenParDate (const void *pcvA, const void *pcvB)
    aussi
    Code:

    static void aff (CIT const *a, size_t n)

    Dans ces deux fonctions, on ne fait que des accès en lecture. 'const' signifie 'lecture seule' (et pas constante' comme on le croit souvent à tord... Le C n'est pas un langage de débutant. Il est bourré de pièges du même ordre. Il ne faut pas chercher à deviner, mais apprendre les définitions exactes. L'intuition ne suffit pas ...)
    .
  • 07/09/2009, 11h26
    Médinoc
    La fonction de comparaison reçoit des pointeurs const, mais qsort() reçoit un pointeur non-const.
  • 07/09/2009, 11h59
    Echap
    Citation:

    Envoyé par Emmanuel Delahaye Voir le message
    dejà, j'ai indiqué comment régler correctement le compilateur pour qu'il t'indique les erreurs :

    mais j'ai bien lu votre article réglage des compilateurs codeblocks mais qu'est ce que je vais copier / coller? quel les options ? j'ai rien trouvé a copier y a que des zone pour coché ou décoché dans l'onglet flags et un champ de saisie d'un text ,j'ai changé de codeblocks 8.02 de intel c/c++ compiler to gnu gcc compilerr setting->compliler and debugger setting->select compiler->gnu gcc compiler votre code correcte selon le premier aucun warning mais selon le deuxième 2 warning !
    Code:

    1
    2
    const CIT *pcA = pcvA;
       const CIT *pcB = pcvB;

    problème de conversion 'from const void* ' to 'const CIT'
    Citation:

    Envoyé par Emmanuel Delahaye Voir le message
    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    Linking console executable: bin\Debug\hello.exe
    C:\dev\hello\main.c:16: warning: unused parameter 'n'
    C:\dev\hello\main.c: In function `CompareCitoyenParDate':
    C:\dev\hello\main.c:31: warning: ISO C forbids nested functions
    C:\dev\hello\main.c:31: error: syntax error before '*' token
    C:\dev\hello\main.c:32: warning: ISO C forbids nested functions
    C:\dev\hello\main.c:32: error: syntax error before '*' token
    C:\dev\hello\main.c:35: error: `pcA' undeclared (first use in this function)
    C:\dev\hello\main.c:35: error: (Each undeclared identifier is reported only once
    C:\dev\hello\main.c:35: error: for each function it appears in.)
    C:\dev\hello\main.c:35: error: `pcB' undeclared (first use in this function)
    C:\dev\hello\main.c: At top level:
    C:\dev\hello\main.c:29: warning: unused parameter 'pcvA'
    C:\dev\hello\main.c:29: warning: unused parameter 'pcvB'
    C:\dev\hello\main.c: In function `remplir':
    C:\dev\hello\main.c:60: warning: char format, different type arg (arg 2)
    C:\dev\hello\main.c:62: warning: char format, different type arg (arg 2)
    Process terminated with status 1 (0 minutes, 0 seconds)
    6 errors, 7 warnings

    Peut être un problème d'ordre de traitement dans la fonction de comparaison. Pas très grave...

    Comme on te l'a déjà fait remarquer, on y verrait beaucoup plus clair si le code était correctement indenté. Voir mes commentaires dans le code :
    Code:

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct fiche
    {
       char nom[10];
       char prenom[11];
       int jour;
       int mois;
       int annee;
       /* -ed-
          int age;
     
          je retire l'age qui est une donnee fluctuante qui peut etre calculee
          au jour le jour... */
    }
    CIT;
     
    /* affichage du tableau */
     
    /* pourquoi  size_t n pas int  ? */
    /* -ed- size_t est un type correct pour les tailles d'objets, donc les nombres
            d'élements de tableaux et donc pour les indices (croissants, car c'est
            un type non signé).
    */
    static void aff (CIT const *a, size_t n)
    {
       /* pourquoi  size_t i pas int i ? */
       size_t i;
       for (i = 0; i < n; i++)
       {
          /* pointeur intermediaire pour alleger l'ecriture */
          CIT const *p = a + i;
     
          /* -ed- evidemment, "2009" pourrait etre evalué automatiquement avec
             time() etc. Et il faudrait aussi tenir compte du mois et du jour ...
           */
          int age = 2009 - p->annee;
          printf ("%-10s %-10s %d ans\n", p->nom, p->prenom, age);
       }
       printf ("\n");
    }
     
    /* fonction utilisateur de comparaison fournie a qsort() */
     
    /* pourquoi const, alors que moi je veux trier et changer les positions ? */
    /* -ed- parce que la fonction de comparaison ne modifie rien.
            Elle se contente de tester, donc de lire les données. */
     
    int CompareCitoyenParDate (const void *pcvA, const void *pcvB)
    {
       /* a quoi ça sert void ? */
       /* -ed- void * signifie "pointeur de n'importe quel type" C'est requis par
          qsort(). La fonction de comparaison est appelée par qsort(). Elle doit
          répondre à des critères d'interface bien précis :
     
          int fonction (void const *, void const *)
     
          ensuite, on doit adapter le codage de la fonction selon les type des données
          à traiter. Les 2 paramètres sont les adresses des données en cours de
          traitement par qsort().
     
        */
     
       /* -ed-
     
          const fiche *pcA = tab;
          const fiche *pcB = tab;
     
          ça, c'est très faux. Il n'y a jamais eu ça dans mes exemples.
     
          Il faut suivre scrupuleusement les indications. Les pointeurs locaux sont
          typés selon les données à traiter ('CIT' ou 'struct fiche', mais pas 'fiche').
          Il prennent comme valeur les 2 valeurs reçues en paramètre :
     
        */
     
       const CIT *pcA = pcvA;
       const CIT *pcB = pcvB;
    /* -ed- si l'ordre de tri ne convient pas, il suffit d'inverser :
     
       const CIT *pcA = pcvB;
       const CIT *pcB = pcvA;
    */
     
       int res;
     
       res = pcA->annee - pcB->annee;
       if (res != 0)
     
          return res;
     
       else
     
          res = pcA->mois - pcB->mois;
     
       if (res != 0)
          return res;
       else
          res = pcA->jour - pcB->jour;
       if (res != 0)
          return res;
     
       return 0;
    }
     
    /* -ed- Je recommande un remplissage 'en dur' pour commencer.
    Ca permet d'avoir un comportement connu et répétitif ...
     
    De plus, ça accélère considérablement l'exécution et donc ça favorise les tests
    intensifs...
     
    J'ai ajoute un paramètre "nombre d'éléments du tableau".
    */
    void remplir (CIT * tab, size_t n)
    {
       size_t i;
    /* -ed
       for (i = 0; i <= 2; i++)
     
       - on utilise pas de valeur en dur, mais un parametre..
       - pour parcourir un tableau de N elements, on utilise :
     
       for (i = 0; i < N; i++)
     
       qui fait varier i de 0 à N-1, comme il se doit.
     
    */
     
       for (i = 0; i < n; i++)
       {
    #if 0
          printf ("nom :\n");
          /* -ed-
             scanf("%s",&tab[i].nom);
     
             encore une fois, .nom est un tableau. Il ne faut pas de '&'
           */
          scanf ("%s", tab[i].nom);
          printf ("prenom :\n");
          scanf ("%s", tab[i].prenom);
          printf ("date de naissance aaaa/mm/jj:\n");
          scanf ("%d%d%d", &tab[i].annee, &tab[i].mois, &tab[i].jour);
    #else
    /* "simulation de saisie "en dur" */
          static const CIT a[] = {
             {"Homer", "Simpson", 12, 1, 1960},
             {"Marge", "Simpson", 8, 2, 1958},
             {"Bart", "Simpson", 22, 8, 1990},
             {"Lisa", "Simpson", 15, 3, 1992},
             {"Maggie", "Simpson", 30, 4, 1995},
          };
     
          tab[i] = a[i];
    #endif
       }
    }
     
    int main (void)
    {
    /* -ed- déplacé. Aucune raison que ce soit une globale */
       CIT tab[4];
     
    /* -ed- sizeof tab / sizeof *tab est un moyen de calculer automatiquement
        le nombre d'élements d'un tableau.
     
        Je l'utilise ici pour indiquer à la fonction de remplissage combien
        d'éléments elle doit traiter (au maximum).
        */
       remplir (tab, sizeof tab / sizeof *tab);
     
       qsort (tab, sizeof tab / sizeof *tab, sizeof *tab, CompareCitoyenParDate);
     
    /* affichage du tableau apres le tri */
       aff (tab, sizeof tab / sizeof *tab);
     
    /* -ed- inutile
       system ("pause");
    */
     
       return 0;
    }

    Ce qui donne :
    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Marge      Simpson    51 ans
    Homer      Simpson    49 ans
    Bart       Simpson    19 ans
    Lisa       Simpson    17 ans
     
     
    Process returned 0 (0x0)   execution time : 0.026 s
    Press any key to continue.


    elle fait partie de la bibliothèque du C.



    La déclaration du prototype de qsort() est dans <stdlib.h>


    C'est un mécanisme de calcul automatique du nombre d'éléments d'un tableau. Il est basé sur la définition d'un tableau (séquence d'éléments de type identique).

    Le nombre d'éléments est donc la taille du tableau (sizeof tab) divisée par la taille d'un élément (sizeof *tab, qui est une forme simplifiée de sizeof tab[0], par exemple).

    euh lalala mais comment j'ai pas vu votre réponse mérçi ,c'est très bien expliqué
  • 07/09/2009, 12h06
    Emmanuel Delahaye
    Citation:

    Envoyé par Echap Voir le message
    selon le deuxième 2 warning !
    Code:

    1
    2
    const CIT *pcA = pcvA;
       const CIT *pcB = pcvB;

    problème de conversion 'from const void* ' to 'const CIT'

    Il faut être certain que le compilateur utilisé est C et non C++. Ajouter ceci au début du code :
    Code:

    1
    2
    3
    4
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif

  • 07/09/2009, 12h12
    Echap
    Citation:

    Envoyé par Emmanuel Delahaye Voir le message
    Il faut être certain que le compilateur utilisé est C et non C++. Ajouter ceci au début du code :
    Code:

    1
    2
    3
    4
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif


    oui il m'affiche l'erreur definie
    Code:

    #error Be sure you are using a C compiler...
    avec les deux autres warning
  • Voir 40 message(s) de cette discussion en une page
    Page 2 sur 3 PremièrePremière 123 DernièreDernière