qsort

qsort - C - Programmation

Marsh Posté le 26-12-2005 à 14:04:43    

Bonjour,
 c'est a moi d'avoir un probleme :
 
je doit trier un tableau de chaines avec qsort, en c, malheureusement la seule chose qu'il me fait, c'est mettre la premiere chaine à la derniere place. Bizarre autant qu'etrange!!
les chaines sont : (le nombre, nb_chaines, est variable mais quatre suffisent pour l'exemple)  
 
char **chaine;
 
chaine[0] = premiere
chaine[1] = deuxieme
chaine[2] = troisieme
chaine[4] = quatrieme
 
int compare_chaines(char *chaine1,char *chaine2)
{
 return strcmp (chaine1,chaine2);
}
 
qsort(chaine,nb_chaines,sizeof(*chaine),compare_chaines);
 
int j;
 
for(j=0;j<nb_chaines;j++)
{
 printf("\nchaines n %d : ",j+1);
 puts(chaine[j]);
}
voici ce qu'il m'affiche :
 
chaine 1 : deuxieme
 
chaine 2 : trosieme
 
chaine 3 : quatrieme
 
chaine 4 : premier
 
ou est mon erreur? aidez moi svp  
merci beaucoup

Reply

Marsh Posté le 26-12-2005 à 14:04:43   

Reply

Marsh Posté le 26-12-2005 à 14:13:00    

Prototype de qsort() :
 

void  qsort(void  *base,  size_t  nel,  size_t  width,
   int (*compar)(const void *, const void *));


 
 
Sinon pour ton char **chaine, l'absence de malloc() c'est juste parce que tu as restreint l'exemple ?
 
 
EDIT : mon message n'est pas très clair : j'ai mis le prototype de qsort() pour que tu te rendes compte que l'on passait à la fonction de comparaison des pointeurs sur les éléments à comparer.


Message édité par Elmoricq le 26-12-2005 à 14:44:19
Reply

Marsh Posté le 26-12-2005 à 14:32:20    

golzinne a écrit :

ou est mon erreur ?


Ton code est incomplet. Peux-tu poster un exemple compilable et réduit au minimum de ton code, par ce que telle quel, il y a tellement d'erreurs possible, que je ne sais pas par quoi commencer...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 26-12-2005 à 14:56:43    

oui, vous avez raison, ce n'est pas tres clair,voici le code :
 
#include<malloc.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
 
int compare_chaines(const void *chaine1,const void *chaine2) ;
int compare_chaines(const void *chaine1,const void *chaine2)
{
 return strcmp (chaine1,chaine2);
}
 
 
Main()
{
 int nb_chaines,i;
 char **chaine ;
 char tampon[256+1];
 
 
 //entrée du nombre de chaines
 printf("combien de chaines voulez vous rentrer? \n" );
 scanf("%d",&nb_chaines);  
 chaine=(char**)malloc(sizeof(char*)*nb_chaines);
 
 //entrée des chaines de caractere
 if (chaine!=0)
 {
     
  scanf("%*c" );
  for(i=0;i<nb_chaines;i++)
  {
   printf("entrez une chaine :" );
   gets(tampon);
   chaine[i]=(char*)malloc(strlen(tampon)+1);
   if (chaine[i]!=0)
   {
    strcpy(chaine[i],tampon);                              
   }
  }
 }
 
        //tri
 qsort(chaine,nb_chaines,sizeof(*chaine),compare_chaines);
               
         //affichage
 for(i=0;i<nb_chaines;i++)
 {
  printf("\nchaines n %d : ",i+1);
  puts(chaine[i]);
 }
}
 

Reply

Marsh Posté le 26-12-2005 à 15:30:21    

Bon alors, très rapidement :
 

Code :
  1. /* malloc.h ?! pas standard... normalement malloc()  
  2.     est dans stdlib.h */
  3. #include<malloc.h>
  4. #include<stdio.h>
  5. #include<string.h>
  6. #include<time.h>
  7. #include<stdlib.h>
  8. /* inutile de prototyper une fonction dont l'imprémentation  
  9.     se trouve juste en dessous ;) */
  10. int compare_chaines(const void *chaine1,const void *chaine2) ;
  11. int compare_chaines(const void *chaine1,const void *chaine2)
  12. {
  13.     /* eh non, comme je le disais, qsort() t'envoie des POINTEURS
  14.         vers tes elements a comparer... donc tes const void *
  15.         cachent en fait des... const char ** ! */
  16. return strcmp (chaine1,chaine2);
  17. }
  18. /* Main() ?! Avec un 'm' majuscule ?!
  19.     Deux prototypes standards de main() :
  20.         int main(void);
  21.         int main(int argc, char **argv); */
  22. Main()
  23. {
  24. int nb_chaines,i;
  25. char **chaine ;
  26. char tampon[256+1];
  27. //entrée du nombre de chaines
  28. printf("combien de chaines voulez vous rentrer? \n" );
  29.         /* bof : scanf() c'est une fonction a deconseiller aux debutants,
  30.             elle n'est pas triviale a utiliser.
  31.             Vois plutot fgets() pour la saisie, et strtol() pour la conversion
  32.             en nombre  
  33.         */
  34. scanf("%d",&nb_chaines);
  35.         /* le cast est inutile, et on peut s'afranchir du typage dans le  
  36.             sizeof, ce qui nous permet de rendre le code plus flexible :
  37.             chaine = malloc( nb_chaines * sizeof *chaine);
  38.             De plus, qu'arrive-t-il si nb_chaines est negatif ? ;)  
  39.         */
  40. chaine=(char**)malloc(sizeof(char*)*nb_chaines);
  41. //entrée des chaines de caractere
  42.         /* Dans un contexte pointeur, on teste avec NULL, et non avec 0 :
  43.                 if ( chaine != NULL )
  44.             Voire :
  45.                 if ( chaine )  
  46.         */
  47. if (chaine!=0)
  48. {
  49.  scanf("%*c" );
  50.  for(i=0;i<nb_chaines;i++)
  51.  {
  52.                         /* Le souci c'est que toute ligne ne se terminant pas par
  53.                             un saut de ligne attendra peut-etre dans le buffer de
  54.                             sortie avant d'etre affichee.
  55.                             Ce qui veut dire que tu ne la verras peut-etre qu'APRES
  56.                             que tu aies tape [ENTREE] !
  57.                             Toute sortie ne se terminant pas par un saut de ligne
  58.                             devrait se voir suivre d'un :
  59.                                 fflush(flux_de_sortie);
  60.                             (ici, flux_de_sortie == stdout)
  61.                         */
  62.   printf("entrez une chaine :" );
  63.                         /* AAAAAAAAAAAAAAAAAAAAAARRRRRRRRGH !!
  64.                             NE JAMAIS UTILISER gets() !
  65.                             gets() est obsolete depuis des annees, et pour une  
  66.                             bonne raison : il n'y a aucun controle de depassement
  67.                             de capacite avec !
  68.                             Cette fonction est a abolir de ton vocabulaire.
  69.                             Pour toujours.
  70.                         */
  71.   gets(tampon);
  72.   chaine[i]=(char*)malloc(strlen(tampon)+1);
  73.   if (chaine[i]!=0)
  74.   {
  75.    strcpy(chaine[i],tampon);                             
  76.   }
  77.  }
  78. }
  79.         //tri
  80. qsort(chaine,nb_chaines,sizeof(*chaine),compare_chaines);
  81.              
  82.          //affichage
  83. for(i=0;i<nb_chaines;i++)
  84. {
  85.                 /* pourquoi puts() en plus du printf() ?
  86.                         printf("\nchaines n°%d : %s", i+1, chaine[i] );
  87.                 */
  88.  printf("\nchaines n %d : ",i+1);
  89.  puts(chaine[i]);
  90. }
  91. }


Reply

Marsh Posté le 26-12-2005 à 17:20:20    


 

Citation :

int compare_chaines(const void *chaine1,const void *chaine2) ;
int compare_chaines(const void *chaine1,const void *chaine2)
{
    /* eh non, comme je le disais, qsort() t'envoie des POINTEURS
        vers tes elements a comparer... donc tes const void *
        cachent en fait des... const char ** ! */
 return strcmp (chaine1,chaine2);
}


 
ok, g pris note des modification, mais je ne comprend pas ce que je dois mettre a la place de mes const viod *chaine1 et const void *chaine2

Message cité 1 fois
Message édité par golzinne le 26-12-2005 à 17:21:59
Reply

Marsh Posté le 26-12-2005 à 17:22:58    

Rien, c'est ce qu'attend qsort() de ta fonction.
 
Par contre tu dois déréférencer ces paramètres pour les passer à strcmp().
 
A l'heure actuelle strcmp() s'attend à des const char*, et toi tu lui passes des const char **.

Reply

Marsh Posté le 26-12-2005 à 18:00:41    

golzinne a écrit :

je ne comprend pas ce que je dois mettre a la place de mes const void *chaine1 et const void *chaine2


Ne modifie pas les paramètres (à part les noms !). Simplement ceux-ci reçoivent les adresses des 2 objets dans le tableau que l'on veut comparer. Les objets étant de type char*, leurs adresses sont de type char **. Pour déréférencer correctement les données, il faut donc initialiser des pointeurs locaux du bon type (soit ... char ** !)

Code :
  1. char **pp1 = chaine1; /* mauvais choix de nom, il faudrait en fait inverser) */
  2. char **pp2 = chaine2;


ensuite le début des chaines se trouve à *p1 et *p2 (ou p1[0] et p[2])? C'est cette valeur que l'on doit passer à strcmp() :  

Code :
  1. return strcmp (*pp1,*pp2);



---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 27-12-2005 à 14:20:21    

OK, je suis parvenu a y arriver grace a tous ces bons conseil. Et en plus ça m'a permit de comprendre l'astuce des pointeurs de pointeurs? Je vais aborder l'examen avec moins de craintes maintenant.
 
Merci beaucoup.

Reply

Marsh Posté le 08-01-2006 à 03:55:55    

golzinne a écrit :

je suis parvenu a y arriver


Je suis heureux d'être content pour toi.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed