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

MFC Discussion :

qsort avec un struct* ?


Sujet :

MFC

  1. #1
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut qsort avec un struct* ?
    Bonjour, voici mon probleme.
    j'ai une struct toute simple. j'ai un tableau de pointeur sur des elements de la structure...
    et je veux le trier avec un qsort.
    ca compile mais ca ne trie rien du tout.
    en debugage (VC++6) je vois bien que l'adresse que je recoit dans ma fonction de trie n'est pas une des adresse de mes objets.
    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
     
    int sort_function( const void *a, const void *b); // prototypage de ma fonction de tri.
     
    struct personne // définition de la structure (en global)
    { char * nom;
       long age;
    };
     
    struct personne* liste[3]; // en global mon tableau
    struct personne a1= {"isa",3}; 
    struct personne a2= {"steph",33};
    struct personne a3= {"fred",30};
     
    int main (void)  // point d'entree
    {
     liste[0]=&a1; // affectations
     liste[1]=&a2;
     liste[2]=&a3;
    int i=0;
     
    // affichage avant...
     for ( i = 0; i <3; i++)  printf("%d %s à %d\n",i, liste[i]->nom,liste[i]->age);
     printf("\n\n");
     
     qsort((void *)liste, 3, sizeof(liste[0]), sort_function);
     
    // affichage apres
     for ( i = 0; i <3; i++)  printf("%d %s à %d\n",i, liste[i]->nom,liste[i]->age);
     
    return 0;
    }
     
    //--- la fonction de tri.
    int sort_function( const void *a, const void *b)
    {
    	// trie par age :
    	struct personne* aa, *bb;
    	aa=(struct personne*)a;
    	bb=(struct personne*)b;
      //--return ((personne*)a)->age -  ((personne*)b)->age ;
     
    	long aaa,bbb; // je detaille, marche pas mieux
    	aaa=aa->age;
    	bbb=bb->age;
    	return aaa-bbb;
    /*   
       // trie par nom :
       return  strcmp(((personne*)a)->nom,((personne*)b)->nom); 
    /**/
    }
    bon voilà, pour l'instant c'est sensé trier pas age (la partie de trie par nom est commenté, mais elle ne marche pas mieux)
    le resultat : on a fred (30) puis isa (3) puis steph (33).
    c'est donc pas trié.

    qqun vois ce qui ne vas pas ??

    merci.

  2. #2
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Par défaut
    Toute petite remarque mais ce ne doit pas être ça : les âges sont des long et ta fonction retourne un int.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 10
    Par défaut
    As-tu essayé d'appeler ta fonction sort_function séparément?

  4. #4
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    Citation Envoyé par Trap D
    Toute petite remarque mais ce ne doit pas être ça : les âges sont des long et ta fonction retourne un int.
    la fonction "sort_function" renvoie toujours un int, c'est normal,
    c'est ce qu'attends qsort.
    il faut renvoyer un negatif si a plus petit que b , un positif si plus grand et zero si egal.

    mais de toute fasson, quand je fait un breakpoint, et que je fait afficher les pointeur que je recoit (a et b) l'adresse n'a rien a voir avec aucunes des 3 adresse de a1 a2 et a3.. donc le contenu de *a et *b est completement bidon.

  5. #5
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    Citation Envoyé par Elji
    As-tu essayé d'appeler ta fonction sort_function séparément?
    oui ca marche tres bien :
    exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%d",sort_function(liste[0],liste[1]));
    me renvoie -30 qui est bien la difference entre 3 et 33.

    le probleme c'est que qsort ne me donne pas liste[0] et liste[1] en paramettre de "sort_function", les adresses que je recoit ne sont pas liste[0] ni [1] ni [2].

    help !!!!!!

  6. #6
    Membre expérimenté Avatar de BertrandA
    Inscrit en
    Août 2003
    Messages
    170
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 170
    Par défaut
    Je n'ai pas regardé ton code en détail. Le code ci-dessous utilise std::vector et la fonction std::sort() de la librairie standard.

    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
     
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <iostream>
     
    using namespace std;
     
    struct personne
    {
       string nom;
       long age;
       personne() : nom(""), age(0) {}
       personne(const string& nom, long age) : nom(nom), age(age) {}
     
       bool operator < (const personne &y) const
       {
       	return age < y.age;
       }
    };
     
    typedef vector<personne> annuaire;
     
    annuaire annu;
    personne a1("isa",   3),
    	      a2("steph", 33),
    	      a3("fred",  30);
     
    int main()
    {
       annu.push_back(a1);
       annu.push_back(a2);
       annu.push_back(a3);
     
       cout << "Appel de std::sort() :" << endl;
     
       sort(annu.begin(), annu.end());
       for (annuaire::const_iterator it=annu.begin(); it != annu.end(); ++it)
       	cout << "Nom : " << (*it).nom << " - Age : " << (*it).age << endl;
     
       return 0;
    }

  7. #7
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Citation Envoyé par BertrandA
    Je n'ai pas regardé ton code en détail. Le code ci-dessous utilise std::vector et la fonction std::sort() de la librairie standard.
    [...]
    Oui. Solution qui en plus sera plus rapide que l'emploi de qsort. Mais je ne sais pas si cela va lui convenir vu qu'il a l'air de programmer en C.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    BertrandA, Luc Hermitte

    merci mais non, car il faut que j'ai la maitrise sur la fonction de trie "sort_function", je ne cherche pas a trier sur le nom uniquement.
    dans la structure il y aura plusieurs criteres,
    par exemple, age, region, nom
    le trie se fera par exemple en premier sur la region, puis sur l'age et enfin sur le nom.
    c'est faisable avec qsort (je l'ai fait en php) mais avec vector, c'est une fonction toute faite, on ne peux pas y mettre les doigts.

    j'y ai passé tout mon weekend, le qsort avec un tableau d'entier ou de chaine ne me pose pas de probleme, mais un tableau de pointeur sur struct, j'y arrive pas.
    je recupere dans ma fonction "sort_function" des void*. mais en fait c'est un pointeur sur un objet du tableau qui lui même est un pointeur sur une instance de ma structure.
    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
     
    int sort_function(const void *a, const void *b)
    {
    // a : est l'adresse de liste[0] (par exemple) - j'ai controlé avec le bedugger
    // *a : est l'adresse de a1 (par exemple) - j'ai controlé avec le debugger
     
    struct personne* aa = *(struct personne*)a; // compile pas
    // il ne veux pas me compiler celà . C2100, 
     
    // le nom doit être (*a)->nom
    printf("%s",(*a)->nom); // compile pas non plus
    //C2100: illegal indirection
    // même en faisant ((struct personne*)(*a))->nom
     
    }
    ce qui m'embete c'est que dns sort_function, qsort ne me donne pas ce qu'il y a dans le tableau liste, mais l'adresse de cet element.
    il faut donc que je dereference "*" et que pendant que j'y suis je le mette du bon type (struct personne*).
    si j'essaye de faire celà, "aa=..." il me jette pourtant aa est du bon type.
    de plus si jessaie de la faire directement (sans passer par un pointeur intermediare :aa) avec "*(a)->nom" il me jette aussi.

    au secours !!!!!!

  9. #9
    Membre expérimenté Avatar de BertrandA
    Inscrit en
    Août 2003
    Messages
    170
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 170
    Par défaut
    Excuse-moi d'insister, mais tu n'as pas l'air de comprendre la puissance de std::sort().

    dans la structure il y aura plusieurs criteres,
    par exemple, age, region, nom
    Je ne vois pas où est le problème.
    le tri se fera par exemple en premier sur la region, puis sur l'age et enfin sur le nom. c'est faisable avec qsort (je l'ai fait en php).
    mais avec vector, c'est une fonction toute faite, on ne peux pas y mettre les doigts.
    Tu te trompes. std::sort() t'oblige à surcharger l'opérateur de comparaison "<" (s'il n'est pas défini par défaut), tu contrôles donc parfaitement ce qui se passe.
    Avec un 3ème champ région, 4 lignes de code supplémentaires suffisent pour trier en fonction de la région, du nom et de l'age.
    On peut même très bien paramétrer les critères.
    Manifestement avec qsort(), ça a l'air un peu plus compliqué...

  10. #10
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    tu as sans doute raison.
    mais je ne connais pas du tout vector,
    et puis est-ce portable ?
    en fait je voudrais eviter tout MFC ou autres...
    je me rends compte que j'aurai du poster ceci dans le forum C (plutot que Visual C++).. a votre avis dois-je le reposter là bas ? (j'aime pas les doubles posts mais je ne sais pas si les specialistes du C font un tour ici de temps en temps ?)

    Citation Envoyé par BertrandA
    Manifestement avec qsort(), ça a l'air un peu plus compliqué...
    non, mais je suis trop nul, voilà tout.

    je ne sais pas, j'hesite entre (*) :
    - attendre qu'un specialiste qsort passe par ici
    - utiliser vector
    - me tirer un balle
    - refaire qsort moi même (a ma sauce)

    (*)cette liste est "trié" dans l'ordre du moins extreme au plus extreme

  11. #11
    Membre expérimenté Avatar de BertrandA
    Inscrit en
    Août 2003
    Messages
    170
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 170
    Par défaut
    Bon j'ai regardé ton code, je pense avoir trouvé ton pb :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       // trie par age :
       struct personne* aa, *bb;
       aa=*((struct personne**)a);
       bb=*((struct personne**)b);
    Les paramètres passés à la fonction de comparaison pointent sur les données à comparer. Or, tu ranges des pointeurs dans ton tableau.
    Les paramètres a et b sont donc des struct personne**.
    Enfin pour trier par nom et par age :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      int iComp = strcmp(aa->nom, bb->nom);
     
      // Même nom ?
      if (iComp == 0)
      {
         // Même age ?
         if ( aa->age == bb->age )
           iComp = 0;
         else
         	 iComp = (aa->age > bb->age) ? 1 : -1;
      }
      return iComp;

  12. #12
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    Citation Envoyé par BertrandA
    Bon j'ai regardé ton code, je pense avoir trouvé ton pb :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       // trie par age :
       struct personne* aa, *bb;
       aa=*((struct personne**)a);
       bb=*((struct personne**)b);
    Les paramètres passés à la fonction de comparaison pointent sur les données à comparer. Or, tu ranges des pointeurs dans ton tableau.
    Les paramètres a et b sont donc des struct personne**.
    Tu es un genie !!!
    BRAVO !

    merci, ca marche nickel !!!!!

    ca fait 3 jours que je tourne autour (!!!) sans y arriver, et pourtant,
    maintenant que je voie le code, ca semble parfaitement logique....
    en plus, en voyant mon post du 14:48 : struct personne* aa = *(struct personne*)a; j'y etait presque ! il me manquai une etoile ! il m'aurait sans doute fallu une bonne semaine pour la trouver celle-là !!!
    vous pouvez pas savoir les truc delir que j'ai essayé ! heureusement qu'il y a ce forum ! merci BertrandA.

    a part celà,

    Je ne suis pas resté sans rien faire : de mon coté j'ai trouvé comment passer autre chose que du "void*"
    et en combinant avec ton code celà donne quelques chose d'assez propre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int sort_function(const struct personne ** a, const struct personne ** b)
    {
       // trie par age : par exemple
       return ((*a)->age -  (*b)->age) ;
    }	
     
    //-- appel de qsort :
      qsort(liste, 3, sizeof(personne*), (int (*)(const void *, const void *))sort_function);
    voilà, c'est nickel chrome !
    vive le C !

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

Discussions similaires

  1. Problème avec un struct et uint_32_t
    Par esteban dans le forum C++
    Réponses: 14
    Dernier message: 02/11/2010, 22h11
  2. utiliser qsort avec void**
    Par dj.motte dans le forum C
    Réponses: 24
    Dernier message: 04/02/2007, 09h05
  3. portabilité avec des struct
    Par elghadi_mohamed dans le forum C
    Réponses: 7
    Dernier message: 04/08/2006, 00h27
  4. Réponses: 22
    Dernier message: 29/01/2005, 11h29
  5. Problème avec [b]struct[/b]
    Par Bouziane Abderraouf dans le forum CORBA
    Réponses: 2
    Dernier message: 17/07/2002, 10h25

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