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 :

tri d'un tableau de struct


Sujet :

C

  1. #21
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Echap Voir le message
    oui tout simplement comme ça !!
    je pense avec les instruction de branchement (break goto ..) ça marche nn ?

    merci je vais lire la participation
    Non ! Il n'y a rien à bricoler. Il faut écrire la fonction de comparaison (qui dépend de la structure des tes donnés et du critère de tri) et appeler correctement qsort avec les bons paramètres. Tout est expliqué ici :

    http://emmanuel-delahaye.developpez....Page8#LXXXVIII

  2. #22
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    Je reste persuadé que, pédagogiquement, il est préférable qu'Echap poursuive, dans un premier temps, son code en définissant sa propre fonction de tri, pas optimisée (mais on s'en fiche), qu'il voit bien la séparation algo de tri / fonction de comparaison et "sente" que la fonction de comparaison c'est "pareil" que le test avec '<' qu'on utiliserait pour trier un tableau d'entiers

    L'utilisation ultérieure de qsort, en adaptant sa fonction de comparaison (structure CITOYEN * vs void *), en sera facilitée. Et puis ça va tout à fait dans le sens du conseil d'Emmanuel Delahaye de "résoudre un problème à la fois" : séparation tri/comparaison puis utilisation de qsort avec adaptation de la fonction de comparaison pour qu'elle "matche" le prototype attendu.

    Sinon, le risque est que ça tourne aux tâtonnements (au fameux "bricolage" évoqué précédemment) dans le passage des paramètres de qsort (je mets un &, je l'enlève, etc...) avec, quand il aura trouvé la bonne forme, un petit arrière goût de "mystérieux" et de "magique".

    Après ce n'est qu'un point de vue, la solution simple et de bon goût étant, évidemment, l'emploi de qsort avec la fonction de comparaison qui va bien. Mais le faire une fois, à la main (et sans se prendre la tête avec l'efficacité du tri) est très formatteur je pense. Et après, on est mûr pour lire le tutoriel proposé et ne plus utiliser que qsort.

  3. #23
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 401
    Par défaut
    Mais moi, je vois ça précisément en sens inverse: Je pense qu'il est préférable de commencer par qsort(), pour avoir une fonction de comparaison qui marche et pouvoir afficher les "bons" résultats, avant de tenter d'implémenter son algorithme (dans un but pédagogique uniquement) où le risque d'erreurs est plus grand.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #24
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    merci pour vos réponses vraiment je suis très fier d'être dans ce forum avec des gens comme vous

  5. #25
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Mais moi, je vois ça précisément en sens inverse: Je pense qu'il est préférable de commencer par qsort(), pour avoir une fonction de comparaison qui marche et pouvoir afficher les "bons" résultats, avant de tenter d'implémenter son algorithme (dans un but pédagogique uniquement) où le risque d'erreurs est plus grand.
    salut maintenant je travail sur la qsort()

  6. #26
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    Citation Envoyé par plxpy Voir le message
    Je reste persuadé que, pédagogiquement, il est préférable qu'Echap poursuive, dans un premier temps, son code en définissant sa propre fonction de tri, pas optimisée (mais on s'en fiche), qu'il voit bien la séparation algo de tri / fonction de comparaison et "sente" que la fonction de comparaison c'est "pareil" que le test avec '<' qu'on utiliserait pour trier un tableau d'entiers

    L'utilisation ultérieure de qsort, en adaptant sa fonction de comparaison (structure CITOYEN * vs void *), en sera facilitée. Et puis ça va tout à fait dans le sens du conseil d'Emmanuel Delahaye de "résoudre un problème à la fois" : séparation tri/comparaison puis utilisation de qsort avec adaptation de la fonction de comparaison pour qu'elle "matche" le prototype attendu.

    Sinon, le risque est que ça tourne aux tâtonnements (au fameux "bricolage" évoqué précédemment) dans le passage des paramètres de qsort (je mets un &, je l'enlève, etc...) avec, quand il aura trouvé la bonne forme, un petit arrière goût de "mystérieux" et de "magique".

    Après ce n'est qu'un point de vue, la solution simple et de bon goût étant, évidemment, l'emploi de qsort avec la fonction de comparaison qui va bien. Mais le faire une fois, à la main (et sans se prendre la tête avec l'efficacité du tri) est très formateur je pense. Et après, on est mûr pour lire le tutoriel proposé et ne plus utiliser que qsort.
    salut plxpy
    oui j'ai voulu passer par la plus part les algorithmes de tri et de recherches (a bull par insertion ....)avec ma méthode avant de passé a la Qsort pour un raison que je ne c'est pas !! peux ètre dans ma tète dur il faut terminé "le premier niveau" parfaitement pour passé a autre niveau ou étape

  7. #27
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Avant d'essayer ton propre algo, as-tu essayé avec qsort() ?
    Bonjour tout le monde voila j’ai essayé avec la qsort() « basé » sur votre réponse ,et la page de Emmanuel Delahaye ,j’ai modifié la fonction de comparaison selon mes critères aussi quelque noms dans les paramètres des fonctions . j’ai complié avec devc++ & codeblocks 0 erreur et 0 warning ,mais leS resultat s ça va pas du tout
    1-il m’affiche l'ordre inver
    2- pour n=3 (tableau de 3)il m'affiche que 2 employés
    voila mon code " la plus part commontaire sont des truc pas claire
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct fiche
     {
    char nom[10] ;
    char prenom[11];
    int jour;
    int mois;
    int annee;
    int age;
    }CIT;
    CIT tab[4];
    /* affichage du tableau */
    static void aff (CIT const *a, size_t n) // pour quoi  size_t n pas int i ????
    {
       size_t i; // pour quoi  size_t i pas int i ????
       for (i = 0; i < 2; i++)
       {
          /* pointeur intermediaire pour alleger l'ecriture */
          CIT const *p = a + i;
          printf ("%-10s %-10s %d ans\n", p->nom, p->prenom, p->age);
       }
       printf ("\n");
    }
     
    /* fonction utilisateur de comparaison fournie a qsort() */
    int CompareCitoyenParDate(const  void *pcvA, const void *pcvB)// pour quoi cont, alors que moi je veux tiré et changé les position ?
    {// a quoi ça sert void ?
    	const fiche *pcA = tab;
    	const fiche *pcB = tab;
    	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;
    }
     
    void remplir(CIT *tab)
    {
    int i;
    for (i=0;i<=2;i++)
    {
        printf("nom :\n");
        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);
    }
    }
    int main (void)
    {
     
       remplir(tab);
       qsort (tab, sizeof tab / sizeof *tab, sizeof *tab,CompareCitoyenParDate);
     
    /* affichage du tableau apres le tri */
       aff (tab, sizeof tab / sizeof *tab);
     
       system("pause");
     
       return 0;
    }
    Autres questions qsort() ,Est ce que cette fonction est prédefini ou quoi ? car il y a que l’appel y a pas de déclaration concernant les paramaitres je trouve
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof tab / sizeof *tab, sizeof *tab,
    de la qsort un peux bizar moi je les comprend pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    qsort (tab, sizeof tab / sizeof *tab, sizeof *tab, compare_age);

  8. #28
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 401
    Par défaut
    1. Qu'appelles-tu l'ordre inverse? Cette fonction est censée trier par date croissante. Si tu veux trier par age croissant, tu dois alors trier par date décroissante. Tu peux soit modifier la fonction, soit faire une fonction inverse qui l'appelle:
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      int CompareCitoyenParDateDecroissante(const void *pcvA, const void *pcvB)
      {
      	int res1 = CompareCitoyenParDate(pcvA, pcvB);
      	int res2 = -res1;
      	return res2;
      }
      • On utilise size_t et non int, car size_t est le type conseillé pour les tailles et indexes de tableaux.
      • La fonction de comparaison prend des pointeurs const en paramètre, car elle n'a rien à modifier ou à échanger. C'est qsort() qui se charge de l'échange, selon le résultat retourné par la fonction de comparaison. La fonction de comparaison ne fait qu'une chose: comparer.
      • Il ne s'agit pas ici de void, mais de void*, qui est un concept radicalement différent. Il s'agit du "pointeur générique", qui peut pointer sur n'importe quoi. La fonction qsort() exige que la fonction de comparaison prenne ce type de pointeur en paramètre.
      • 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.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #29
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Echap Voir le message
    Bonjour tout le monde voila j’ai essayé avec la qsort() « basé » sur votre réponse ,et la page de Emmanuel Delahaye ,j’ai modifié la fonction de comparaison selon mes critères aussi quelque noms dans les paramètres des fonctions . j’ai complié avec devc++ & codeblocks 0 erreur et 0 warning ,
    dejà, j'ai indiqué comment régler correctement le compilateur pour qu'il t'indique les erreurs :
    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
     
    -------------- 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
    mais leS resultat s ça va pas du tout
    1-il m’affiche l'ordre inverse
    Peut être un problème d'ordre de traitement dans la fonction de comparaison. Pas très grave...
    2- pour n=3 (tableau de 3)il m'affiche que 2 employés
    voila mon code " la plus part commentaire sont des truc pas claire
    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 : 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
     
    #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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.
    Autres questions qsort() ,Est ce que cette fonction est prédefini ou quoi ?
    elle fait partie de la bibliothèque du C.


    car il y a que l’appel y a pas de déclaration concernant les paramaitres
    La déclaration du prototype de qsort() est dans <stdlib.h>

    je trouve
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof tab / sizeof *tab, sizeof *tab,
    de la qsort un peux bizarre moi je les comprend pas
    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).

  10. #30
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    1. 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.
    Je préfère parler de "nombre d'éléments" que de "taille" ...

  11. #31
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    1. Qu'appelles-tu l'ordre inverse? Cette fonction est censée trier par date croissante. Si tu veux trier par age croissant, tu dois alors trier par date décroissante. Tu peux soit modifier la fonction, soit faire une fonction inverse qui l'appelle:
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      int CompareCitoyenParDateDecroissante(const void *pcvA, const void *pcvB)
      {
      	int res1 = CompareCitoyenParDate(pcvA, pcvB);
      	int res2 = -res1;
      	return res2;
      }
      • On utilise size_t et non int, car size_t est le type conseillé pour les tailles et indexes de tableaux.
      • La fonction de comparaison prend des pointeurs const en paramètre, car elle n'a rien à modifier ou à échanger. C'est qsort() qui se charge de l'échange, selon le résultat retourné par la fonction de comparaison. La fonction de comparaison ne fait qu'une chose: comparer.
      • moi ce que je veux c'est le plus àgé doit etre afficher le premier merci pour l'idée de la fonction inverse c'est nouveau pour moi je vais l'étudier
        Citation Envoyé par Médinoc Voir le message
      • Il ne s'agit pas ici de void, mais de void*, qui est un concept radicalement différent. Il s'agit du "pointeur générique", qui peut pointer sur n'importe quoi.
    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
  12. 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 Médinoc

  • #32
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    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).

    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.

  • #33
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 401
    Par défaut
    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:
    Le vrai type de a sera en réalité unsigned int.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  • #34
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    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
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    int CompareCitoyenParDate (const void *pcvA, const void *pcvB)
    aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static void aff (CIT const *a, size_t n)
    peux etre je suis entrain de dire n'importe quoi mais je doit le prononcé pour finir avec les fausse méthode de pensé

  • #35
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    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:
    Le vrai type de a sera en réalité unsigned int.
    emmm maintenant je comprend

  • #36
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    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().

    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...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int CompareCitoyenParDate (const void *pcvA, const void *pcvB)
    aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ...)
    .

  • #37
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 401
    Par défaut
    La fonction de comparaison reçoit des pointeurs const, mais qsort() reçoit un pointeur non-const.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  • #38
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : 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
     
    -------------- 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 : 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
     
    #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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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é

  • #39
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Echap Voir le message
    selon le deuxième 2 warning !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif

  • #40
    Membre confirmé
    Développeur Web
    Inscrit en
    Novembre 2008
    Messages
    146
    Détails du profil
    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Novembre 2008
    Messages : 146
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif
    oui il m'affiche l'erreur definie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #error Be sure you are using a C compiler...
    avec les deux autres warning

  • + Répondre à la discussion
    Cette discussion est résolue.
    Page 2 sur 3 PremièrePremière 123 DernièreDernière
    ActualitésFAQ CTutoriels CLivres CCompilateurs et outils CSources CGTK+

    Discussions similaires

    1. Tri d'un tableau en 2D
      Par sniperseb dans le forum C
      Réponses: 4
      Dernier message: 05/01/2006, 17h33
    2. Réponses: 6
      Dernier message: 16/09/2005, 11h30
    3. tri d'un tableau à 2 dimensions
      Par dede92 dans le forum C
      Réponses: 4
      Dernier message: 19/02/2005, 19h29
    4. [langage] Probleme de tri d'un tableau de tableau
      Par Ludo167 dans le forum Langage
      Réponses: 1
      Dernier message: 25/08/2004, 11h32
    5. [] Tri d'un tableau par ordre alphabétique
      Par cafeine dans le forum VB 6 et antérieur
      Réponses: 3
      Dernier message: 17/09/2002, 09h43

    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