Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1205 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Problème sur un exo de C [RESOLU]

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Problème sur un exo de C [RESOLU]

n°1274578
snipred
Posté le 29-12-2005 à 18:16:07  profilanswer
 

Bonjour,  
 
J'ai un problème avec cet exo :  :cry:  
 
http://img416.imageshack.us/img416/7910/exo2vr.jpg
 
J'ai réussis à faire la fonction saisir et celle d'affichage (enfin pas sûr pour celle-là) mais la suite je ne comprends pas comment faire. De plus, dans l'état actuel des choses, le programme plante après que j'ai saisi la première chaîne.
 
Merci par avance de votre aide !  :jap:  :jap:  
 
Je mets ici ce que j'ai déjà fait :
 
 

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. void saisi(char **t,int nb) //Fonction de saisie du Tableau
  5. {
  6.     int i;
  7. char chaine[80];
  8.     for (i=0;i<nb;i++)
  9.     {
  10.         printf("Veuillez saisir la chaine de caracteres %d :\n",i+1);
  11.         gets(chaine);
  12.         t[i]=(char*)malloc((sizeof(char))*(strlen(chaine)+1));
  13. //On alloue dynamiquement la longeur de chaine au pointeur  
  14.         if(t[i]==NULL)
  15.  {
  16.                        printf("Pas assez de memoire" );
  17.   i=i-1;//En cas d'erreur, seconde saisie possible
  18.  }
  19.  else
  20.   strcpy(t[i],chaine); // On copie la chaine "chaine" dans t[i]
  21.     }
  22. }
  23. void affichage(char **t,int nb) // Fonction d'affichage du tableau
  24. {
  25. int i;
  26. for (i=0;i<=nb;i++)
  27. {
  28.      printf("%s  \n",t[i]);
  29. }
  30. }
  31. int main()
  32. {
  33.    
  34. char **t;
  35. int nb;
  36. do
  37.         {
  38.            printf("Veuillez saisir le nombre de chaines de caracteres a traiter : (entre 1 et 15)\n" );
  39.    scanf("%d",&nb);
  40.    getchar();
  41. }while((nb<1)||(nb>15));
  42. saisi(t,nb);
  43. affichage(t,nb);
  44. return 0;
  45. }

Message cité 1 fois
Message édité par snipred le 31-12-2005 à 09:53:09

---------------
Athlon 3500+ Core Venice/Asustek A8N SLI PRENIUM/DD Seagate 160 Go 8 Mo de cache/Leadtek 6600GT 128Mo/Creative Audigy 2 ZS/2X512 Mo Corsair Value PC 3200/Hiper Type R 480 W/Boitier Textorm 974MB
mood
Publicité
Posté le 29-12-2005 à 18:16:07  profilanswer
 

n°1274584
slash33
Posté le 29-12-2005 à 18:35:34  profilanswer
 

Bon je vais t'éviter des problèmes : ici c'est la section C++ (note bien le ++) ce que tu proposes ici c'est du C.
 
Déplace ton message dans la catégorie C.

n°1274588
snipred
Posté le 29-12-2005 à 18:40:17  profilanswer
 

Excusez-moi, je pensais que c'était du C++ car c'est ce que j'apprends en C++. De plus, il est écrit sur la feuille d'exercice : "Bases de la programmation C++". Il est vrai que l'on m'a déjà plusieurs fois que ma prof (IUT Info) ne nous donner pas des cours de C++ mais de C en fait.
 
Encore une fois désolé
 
Qu'est-ce que je fais ? Je préviens les modos pour qu'il supprime ce post et je le refais dans la rubrique C ?

n°1274603
gilou
Modérateur
Modzilla
Posté le 29-12-2005 à 19:16:55  profilanswer
 

Je l'ai change de cat. A toi d'editer le titre.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°1274643
Elmoricq
Modérateur
Posté le 29-12-2005 à 20:51:26  profilanswer
 

Je me permets de commenter ton programme pour te signaler les problèmes.
N'hésite pas à demander s'il y a quelque chose que tu ne captes pas :
 

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. /* Si tu veux creer un tableau de chaine et le retourner par reference,  
  5.     alors il faut que tu crees un pointeur vers ce tableau de chaine.
  6.     Ce qui donne le prototype suivant :
  7.         void saisie(char ***t, int nb);
  8.     Mais si rien ne justifie un passage par reference, alors fait plutot
  9.     en sorte que ta fonction retourne un char**, c'est bien plus simple :
  10.         char **saisie(int nb);
  11. */
  12. void saisie(char **t,int nb) //Fonction de saisie du Tableau
  13. {
  14.     int i;
  15.     char chaine[80];
  16.     for ( i=0; i<nb; i++ )
  17.     {
  18.         printf("Veuillez saisir la chaine de caracteres %d :\n",i+1);
  19.         /* Surtout pas. La fonction gets() est à bannir de ton vocabulaire.
  20.             Pour toujours.
  21.             Cette fonction est obsolète depuis des années, et n'existe encore
  22.             que pour des raisons de compatibilité.
  23.             Le problème de gets() est qu'il n'y a absolument aucun controle
  24.             de depassement de capacite.
  25.             Bref, utilise fgets() a la place  
  26.         */
  27.         gets(chaine);
  28.         /* le cast est inutile, et le nombre de parentheses alourdi le code.
  29.             Un code illisible, c'est un code qui cache des bugs.
  30.             Tu peux l'ecrire comme suit :
  31.                 t[i] = malloc( (strlen(chaine) + 1) * sizeof char );
  32.             Ou encore :
  33.                 t[i] = malloc( (strlen(chaine) + 1) * sizeof **t );
  34.             Qui plus est tu alloues de la memoire pour ce que contient une case  
  35.             de "t", mais de ce que je peux voir, cette variable ne contient pas  
  36.             de case pour commencer. D'ou plantage.
  37.             Donc avant ce malloc(), tu dois en faire un autre pour allouer
  38.             de la place pour y stocker nb chaines de caracteres (de type char*)
  39.         */
  40.         t[i]=(char*)malloc((sizeof(char))*(strlen(chaine)+1));
  41.         //On alloue dynamiquement la longeur de chaine au pointeur  
  42.         if( t[i] == NULL )
  43.         {
  44.             /* pour les erreurs, il vaut mieux les sortir sur le flux de sortie
  45.                 d'erreur standard : stderr
  46.                 On peut y acceder avec fprintf() :
  47.                     fprintf(stderr, "Echec allocation\n" );
  48.                 Remarque : pour te montrer un autre flux que tu utilises sans
  49.                 le savoir, tu peux ecrire ton printf() avec fprintf() et le flux
  50.                 de sortie standard, stdout :
  51.                     fprintf(sdout, "Pas assez de memoire\n" );
  52.                 J'ajouterais que si tu ne mets pas de saut de ligne a la fin d'une
  53.                 impression, il te faut forcer le vidage du buffer du flux, pour que
  54.                 l'affichage soit immediat. Sinon, ta chaine peut attendre en memoire
  55.                 jusqu'au prochain saut de ligne.
  56.                 Donc soit tu ajoutes un caractere '\n' a la fin, soit tu utilises la
  57.                 commande fflush() :
  58.                     fflush(stdout);
  59.             */
  60.             printf("Pas assez de memoire" );
  61.             /* Bof : en principe on ne doit jamais modifier le parametre  
  62.                 d'incrementation d'une boucle for(;;). Ca conduit vers trop d'erreurs.
  63.                 Et puis est-ce raisonnable de vouloir tenter d'autres saisies
  64.                 apres un probleme d'allocation d'aussi petite taille ?
  65.             */
  66.             i=i-1;//En cas d'erreur, seconde saisie possible
  67.         }
  68.         else
  69.             strcpy(t[i], chaine); // On copie la chaine "chaine" dans t[i]
  70.     }
  71. }
  72. void affichage(char **t,int nb) // Fonction d'affichage du tableau
  73. {
  74.     int i;
  75.     for (i=0;i<=nb;i++)
  76.     {
  77.         printf("%s  \n",t[i]);
  78.     }
  79. }
  80. int main()
  81. {
  82.     char **t;
  83.     int nb;
  84.     do
  85.     {
  86.         printf("Veuillez saisir le nombre de chaines de caracteres a traiter : (entre 1 et 15)\n" );
  87.         /* Je n'aime pas scanf(), c'est une fonction dangereuse si elle est mal utilisee,
  88.             comme ici.
  89.             Il faut agir avec precaution, ne serait-ce qu'en testant son code retour.
  90.             Bref, utilise plutot fgets(), et converti la chaine en nombre avec strtol()
  91.         */
  92.         scanf("%d",&nb);
  93.         getchar();
  94.     /* parentheses qui alourdissent le code. Ce n'est pas faux, mais ceci est
  95.         beaucoup plus leger a lire :
  96.         } while ( nb < 1 || nb > 15 );
  97.     */
  98.     } while((nb<1)||(nb>15));
  99.     /* cf. ma correction sur ton prototype de la fonction saisie(),  
  100.         tu dois passer une reference sur ta variable t.
  101.         Donc apres avoir change ta fonction saisie pour recevoir
  102.         une variable de type char***, passe l'adresse de t :
  103.             saisie( &t, nb);
  104.     */
  105.     saisie(t,nb);
  106.     affichage(t,nb);
  107.     return 0;
  108. }


 
 
EDIT : je viens de voir que c'est ton prof qui te demande d'utiliser gets().
Je demande une lapidation sur la place publique.


Message édité par Elmoricq le 29-12-2005 à 20:52:46
n°1274820
snipred
Posté le 30-12-2005 à 10:21:50  profilanswer
 

En effet, c'est ma prof qui nous oblige à utiliser toutes les fonctions inderdites et déconseillés comme malloc, free, scanf, printf, gets()...
 
 
Pour la suite, comment faire, je ne vois pas trop, la permutation je vois ce qu'il faut faire, mais pour y retranscrire ?
 
Merci de votre aide !
 
PS : J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
 

Code :
  1. void tri(char**chaine,int nb) //Fonction de trie des chaînes
  2. {
  3. permut(chaine[i],chaine[j]);
  4. }
  5. void permut(char** chaine1,char** chaine2) // Fonction permutation
  6. {
  7. char temp;
  8.     temp=**ch1;
  9. **ch1=**ch2;
  10. **ch2=temp;
  11. }

Message cité 2 fois
Message édité par snipred le 30-12-2005 à 10:42:07
n°1274825
Elmoricq
Modérateur
Posté le 30-12-2005 à 10:43:14  profilanswer
 

snipred a écrit :

En effet, c'est ma prof qui nous oblige à utiliser toutes les fonctions inderdites et déconseillés comme malloc, free, scanf, printf, gets()...


 
Il n'y a que gets() qui soit déconseillé. Les autres que tu cites sont tout à fait standard.
 
 

snipred a écrit :

Sinon, vous avez une explication pour le fait que ce programme ne fonctionne pas après que l'on ait renseigné la première chaîne ?


 
Euh... Y a-t-il quelque chose que tu ne comprends pas dans les commentaires que j'ai mis dans ton source ?
 

snipred a écrit :

PS : J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
 

Code :
  1. void tri(char**chaine,int nb) //Fonction de trie des chaînes
  2. {
  3. permut(chaine[i],chaine[j]);
  4. }
  5. void permut(char** chaine1,char** chaine2) // Fonction permutation
  6. {
  7. char temp;
  8.     temp=**ch1;
  9. **ch1=**ch2;
  10. **ch2=temp;
  11. }



 
Ouh la.
 
Bon, reprenons.
Une chaîne de caractères, en C, est en fait une zone mémoire comprenant une suite de données de type "char", suite terminée par un char de valeur 0 pour marquer la fin de la chaîne (si pas de 0, on continue de lire jusqu'à en trouver un, ça peut aller jusqu'au plantage, donc il est vital de le prévoir et  
de le gérer).
 
Donc ceci :

Code :
  1. char caractere = 'a';
  2. printf("%c\n", caractere);


C'est pour un caractère.
 
Ceci :

Code :
  1. const char *chaine = "Voici une chaîne de caractères";
  2. printf("%s\n", chaine);


C'est pour une chaîne. Ici j'ai ajouté qu'il s'agissait d'une chaîne constante, pour qu'elle soit dynamique il aurait fallu la définir comme :  
char chaine[une_taille_max];
Ou bien en char*, avec un appel à malloc() pour lui assigner une taille définie.
Note que lorsque tu prévois une taille pour ta chaîne, tu dois penser au zéro terminal.
 
 
Et enfin, ceci :

Code :
  1. char **plein_de_chaines;


Représente soit l'adresse d'un char* (donc un &chaine par exemple, ce qui donne bien un char**), soit un pointeur vers une zone contenant des pointeurs vers des char.
 
Schéma :

[char]
 
[char*] => [char 0](, [char 1], [char 2], ..., [char n])
 
[char **] => [char* 0](, [char* 1], [char* 2], ..., [char* n])
              |
              |=>[char 0](, [char 1], [char 2], ..., [char n])


 
Et ainsi de suite.
On peut continuer à l'infini, virtuellement on peut avoir un char******, mais bon si tu as besoin d'un truc pareil, c'est que tu as un sérieux problème de conception. [:dawa]
 
Extrapolons au char*** :


[char***] => [char** 0](, [char** 1], [char** 2], ...,  [char** n])
              |
              |=> [char* 0](, [char* 1], [char* 2], ..., [char* n]
                  |
                  |=> [char 0](, [char 1], [char 2], ..., [char n])


 
(remarque : c'est une "notation" symbolique, ce n'est pas du C)

n°1274844
snipred
Posté le 30-12-2005 à 11:15:09  profilanswer
 

Citation :

Il n'y a que gets() qui soit déconseillé. Les autres que tu cites sont tout à fait standard.


 
En fait, on est censé être en cours de C++ avec cette prof et il me semblait que c'était plutôt alloué au C ces fonctions.  
 
 

Citation :

Euh... Y a-t-il quelque chose que tu ne comprends pas dans les commentaires que j'ai mis dans ton source ?


 
J'ai vu après seulement que vous expliquiez pour le plantage mais il est vrai, je ne comprends pas vraiment ce qu'il faut faire...
 

Citation :

Snipred a écrit :
 
PS : J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
 

Code :
  1. Code :
  2.    1.
  3.       void tri(char**chaine,int nb) //Fonction de trie des chaînes
  4.    2.
  5.       {
  6.    3.
  7.           permut(chaine[i],chaine[j]);
  8.    4.
  9.       }
  10.    5.
  11.      
  12.    6.
  13.       void permut(char** chaine1,char** chaine2) // Fonction permutation
  14.    7.
  15.       {
  16.    8.
  17.           char temp;
  18.    9.
  19.          temp=**ch1;
  20.   10.
  21.           **ch1=**ch2;
  22.   11.
  23.           **ch2=temp;
  24.   12.
  25.       }



 
 
 
Apparemment j'ai rien compris  [:ajacciu20]
 

Citation :


pour qu'elle soit dynamique il aurait fallu la définir comme :  
char chaine[une_taille_max];
Ou bien en char*, avec un appel à malloc() pour lui assigner une taille définie.
Note que lorsque tu prévois une taille pour ta chaîne, tu dois penser au zéro terminal.


 
C'est là que je comprends pas trop...
 
 
Je suis vraiment désolé d'être aussi nul... [:armelanuel]

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 11:17:34
n°1274850
Elmoricq
Modérateur
Posté le 30-12-2005 à 11:21:53  profilanswer
 

snipred a écrit :

Citation :

Il n'y a que gets() qui soit déconseillé. Les autres que tu cites sont tout à fait standard.


 
En fait, on est censé être en cours de C++ et il me semblait que c'était plutôt alloué au C ces fonctions.


 
 [:pingouino]  
Euh effectivement, tout ça n'a rien à voir avec le C++.
En C++ tu devrais jouer avec les classes, les namespace, malloc()/free() devient new/delete, les flux ne sont plus utilisés pareil...
 
Bref, entre gets(), et le C++_qui_est_en_fait_du_C (d'un autre âge, en plus), ton prof est à jeter aux orties.
 
Pour le C, prends-toi un bon livre, type "Le Langage C", de Kernighan&Ritchie.  
Pour le C++, qui est une approche bien différente du C, je ne sais pas... Je crois qu'il y a un "thinking in C++" de Bruce Eckel, si ses bouquins C++ sont de même qualité que ceux pour Java, tu peux y aller les yeux fermés.
 
 
 

snipred a écrit :

Citation :


pour qu'elle soit dynamique il aurait fallu la définir comme :  
char chaine[une_taille_max];
Ou bien en char*, avec un appel à malloc() pour lui assigner une taille définie.
Note que lorsque tu prévois une taille pour ta chaîne, tu dois penser au zéro terminal.


 
C'est là que je comprends pas trop...[/quote]


 
Hmm, je pense qu'il te faudrait un cours complet. Comme au-dessus je te conseille le K&R, mais tu peux commencer à lire ces deux pages :
http://mapage.noos.fr/emdel/init_c.htm
http://mapage.noos.fr/emdel/notes.htm
 
Tu devrais avoir les idées plus claires ensuite (tu peux globalement parcourir l'ensemble du site http://mapage.noos.fr/emdel , il contient pas mal d'informations intéressantes)

n°1274916
blackgodde​ss
vive le troll !
Posté le 30-12-2005 à 12:14:40  profilanswer
 

mais ca existe vraiment des "profs" comme ca ? :o


---------------
-( BlackGoddess )-
mood
Publicité
Posté le 30-12-2005 à 12:14:40  profilanswer
 

n°1274934
snipred
Posté le 30-12-2005 à 12:45:35  profilanswer
 

Et oui, désolé pour moi...

n°1274936
Sve@r
Posté le 30-12-2005 à 12:49:20  profilanswer
 

snipred a écrit :

Je mets ici ce que j'ai déjà fait :
 

Code :
  1. int main()
  2. {
  3.    
  4. char **t;
  5. int nb;
  6. do
  7.         {
  8.            printf("Veuillez saisir le nombre de chaines de caracteres a traiter : (entre 1 et 15)\n" );
  9.    scanf("%d",&nb);
  10.    getchar();
  11. }while((nb<1)||(nb>15));
  12. saisi(t,nb);
  13. affichage(t,nb);
  14. }


De plus, dans l'état actuel des choses, le programme plante après que j'ai saisi la première chaîne.


 
Tu as oublié la phrase "on allouera dynamiquement l'espace nécessaire pour stocker un tableau de "N" pointeurs sur des chaînes de caractères que tu n'as pas fait donc tu n'as pas l'espace pour stocker N pointeurs donc ça plante
Il te faut insérer, avant l'appel de "saisi()" l'instruction suivante:
t=malloc(nb * sizeof(char *));
 
Ensuite il ne faudra pas oublier toute la phase de libération mémoire => je te propose la fonction suivante

Code :
  1. void clean(char **t, int nb)
  2. {
  3.      int i;
  4.      if (t == NULL)
  5.         return;
  6.      for (i=0; i < nb; i++)
  7.      {
  8.          if (t[i])
  9.            free(t[i]);
  10.      }
  11.      free(t);
  12. }


 
Ensuite, en fin de pgm, tu appelles "clean(t, nb)"
 

snipred a écrit :

En effet, c'est ma prof qui nous oblige à utiliser toutes les fonctions inderdites et déconseillés comme malloc, free, scanf, printf, gets()...


Je vois pas où t'es allé chercher que "malloc/free", "scanf" et "printf" étaient interdits et déconseillés. Eventuellement "scanf" serait peut-être à déconseiller mais je vois vraiment pas comment on peut faire du C sans jamais faire de printf, malloc ou free...
 

snipred a écrit :

J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
 

Code :
  1. void permut(char** chaine1,char** chaine2) // Fonction permutation
  2. {
  3. char temp;
  4.     temp=**ch1;
  5. **ch1=**ch2;
  6. **ch2=temp;
  7. }



Bon, cette fonction doit permuter des pointeurs sur des chaînes de caractères et non des pointeurs de pointeurs

Code :
  1. void permut(char** chaine1,char** chaine2) // Fonction permutation
  2. {
  3. char *temp;
  4.     temp=(*ch1);
  5. *ch1=(*ch2);
  6. *ch2=temp;
  7. }


 

snipred a écrit :

J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
 

Code :
  1. void tri(char**chaine,int nb) //Fonction de trie des chaînes
  2. {
  3. permut(chaine[i],chaine[j]);
  4. }



 
Là, je vois pas à quoi sert "nb". En revanche, il faut passer "&chaine[i]" et "&chaine[j]" à permut. En fait, c'est un peu subtil. Etant donné que "permut" doit permuter (donc modifier) deux pointeurs, il faut lui passer l'adresse de ces pointeurs pour qu'elle puisse les modifier (comme on passe l'adresse d'une variable à "scanf" pour qu'elle puisse la saisir)


Message édité par Sve@r le 30-12-2005 à 13:14:25
n°1274950
snipred
Posté le 30-12-2005 à 13:33:43  profilanswer
 

Merci beaucoup de ton aide !
 
Comme je le disais, pour ce qui est des scanf et printf, on les utilise alors qu'on ne devrait pas à priori dans un cours de  C++. Je ne savais pas que je faisais du C en fait car ils nous apprennent que ce sont des fonctions de base de C++. Bref, difficile de comprends ce que l'on fait après.  
 

Citation :

Il te faut insérer, avant l'appel de "saisi()" l'instruction suivante:
t=malloc(nb * sizeof(char *));


 
Il m'affiche une conversion invalide.
 
Pour le nb dans Tri, on ne va pas utiliser une double boucle for pour chaîne[i] et chaine[j]?

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 13:36:42
n°1274957
Sve@r
Posté le 30-12-2005 à 13:50:36  profilanswer
 

snipred a écrit :

Merci beaucoup de ton aide !
 
Comme je le disais, pour ce qui est des scanf et printf, on les utilise alors qu'on ne devrait pas à priori dans un cours de  C++. Je ne savais pas que je faisais du C en fait car ils nous apprennent que ce sont des fonctions de base de C++. Bref, difficile de comprends ce que l'on fait après.


C'est vrai que en C++, "scanf/printf" deviennent inutile car on peut utiliser les flux "cin/cout". Idem pour "malloc/free" avantageusement remplacés par "new/delete"...
 

snipred a écrit :

Citation :

Il te faut insérer, avant l'appel de "saisi()" l'instruction suivante:
t=malloc(nb * sizeof(char *));


 
Il m'affiche une conversion invalide.


Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ???
Au pire caste le => t=(char**)malloc(nb *sizeof(char*));
 

snipred a écrit :

Pour le nb dans Tri, on ne va pas utiliser une double boucle for pour chaîne[i] et chaine[j]?


Quand la fonction sera complètement écrite, nb sera effectivement très utile. Mais telle que je la voyais, je voyais pas à quoi servait "nb". Mais c'est vrai qu'il le faut...

Message cité 1 fois
Message édité par Sve@r le 30-12-2005 à 13:52:14
n°1274963
snipred
Posté le 30-12-2005 à 14:12:43  profilanswer
 

Citation :

Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ???
Au pire caste le => t=(char**)malloc(nb *sizeof(char*));


 
Effectivement, il fallait le caster, j'avais essayer mais en mettant char*, ce qui n'arrangeait rien...
Jusque l'affichage, tout marche nikel...
 
Pour la suite, je vois pas trop comment faire, j'ai cette horreur pour le moment que je vais éditer:
 

Code :
  1. void tri(char**chaine,int nb) //Fonction de tri des chaînes
  2. {
  3.      int i,j,petit;
  4.    
  5.      for (i=0;i<nb;i++)
  6.      {
  7.         for (j=nb-1;j=0;j--)
  8.        {
  9.            if (&chaine[i]<&chaine[j])
  10.               permut(&chaine[i],&chaine[j]);
  11.        }
  12.      }
  13. }
  14. void permut(char** ch1,char** ch2) // Fonction permutation
  15.       {
  16.           char *temp;
  17.           temp=(*ch1);
  18.           *ch1=(*ch2);
  19.           *ch2=temp;
  20.       }


 
Autre question, ceci devient inutile avec la fonction clean ?
 

Code :
  1. if(t[i]==NULL)
  2.  {
  3.             printf("Pas assez de memoire" );
  4.  }

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 15:51:54
n°1274964
Elmoricq
Modérateur
Posté le 30-12-2005 à 14:22:44  profilanswer
 

Pour le cast, tu dois utiliser un compilateur obsolète... comme ton cours.
 
Au pif : Borland Turbo C ?

n°1274989
Sve@r
Posté le 30-12-2005 à 15:29:47  profilanswer
 

snipred a écrit :

Citation :

Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ???
Au pire caste le => t=(char**)malloc(nb *sizeof(char*));


 
Effectivement, il fallait le caster, j'avais essayer mais en mettant char*, ce qui n'arrangeait rien...


Ben non !!! "t" étant de type "char **" il faut lui donner une valeur de type "char **" et non "char *" !!!
 

snipred a écrit :

Pour la suite, je vois pas trop comment faire, j'ai cette horreur pour le moment que je vais éditer:
 

Code :
  1. void tri(char**chaine,int nb) //Fonction de tri des chaînes
  2. {
  3.      int i,j,petit;
  4.    
  5.      for (i=0;i<nb;i++)
  6.      {
  7.         for (j=nb-1;j=0;j++)
  8.        {
  9.            if (&chaine[i]<&chaine[j])
  10.               permut(&chaine[i],&chaine[j]);
  11.        }
  12.      }
  13. }



Horreur c'est bien le mot qui convient. Essaye de réfléchir un peu. Que contiennent "&chaine[i]"  et "&chaine[j]" ? Deux adresses ! Mais la valeur de ces adresses influe-t-elle sur la valeur des chaines sur lesquelles elles pointent ?
Autrement dit, est ce que, si "&chaine[i]" est inférieure à "&chaine[j]" cela te permet de dire que la chaine pointée par "chaine[i]" est inférieure à celle pointée par "chaine[j]" ???
 
Pour comparer deux chaines, il faut comparer individuellement chaque caractère qui les composent. Heureusement il y a la fonction "strcmp" qui a déjà été écrite par d'autres programmeurs talentueux et que tu as le droit d'utiliser...
 
Autre chose => for (j=nb -1; j=0; j++) => Va réviser la syntaxe de la boucle "for"
D'ailleurs ton algo en lui-même me semble pas terrible. je te propose l'algo du tri à bulle qui est le plus simple des tris existants


faire
     mettre flag à 0
     boucle du premier élément jusqu'à l'avant dernier
     faire
          si elem[i] > elem[i + 1]
               permuter elem[i] et elem[i + 1]
               mettre flag à 1
         fin si
     fin faire
fin faire et recommencer la boucle tant que flag vaut 1


 

snipred a écrit :

Autre question, ceci devient inutile avec la fonction clean ?
 

Code :
  1. if(t[i]==NULL)
  2.  {
  3.             printf("Pas assez de memoire" );
  4.  }



Non ! la fonction "clean" sert à nettoyer tout "t" une fois que tu n'en n'as plus besoin. Mais tu doit toujours, lorsque tu alloues un pointeur, vérifier que l'allocation a réussie. D'ailleurs tu dois aussi le faire avec ton "t=(char **)malloc(...)"
 

Elmoricq a écrit :

Pour le cast, tu dois utiliser un compilateur obsolète... comme ton cours.
 
Au pif : Borland Turbo C ?


 :lol:  :lol:  :lol:


Message édité par Sve@r le 30-12-2005 à 17:52:59
n°1275001
snipred
Posté le 30-12-2005 à 16:22:26  profilanswer
 

Bon j'en suis arrivé là mais y'a encore un peu de chemin...
En tout cas, il n'y a plus d'erreurs...
Mais ça ne marche pas pour autant...
 

Code :
  1. #include<iostream.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<string.h>
  5. void saisi(char **t,int nb) //Fonction de saisie du Tableau
  6. {
  7.     int i;
  8. char chaine[80];
  9.     for (i=0;i<nb;i++)
  10.     {
  11.         printf("Veuillez saisir la chaine de caracteres %d :\n",i+1);
  12.         gets(chaine);
  13.         t[i]=(char*)malloc((sizeof(char))*(strlen(chaine)+1));//On alloue dynamiquement la longeur de chaine au pointeur
  14.         if(t[i]==NULL)
  15.  {
  16.             printf("Pas assez de memoire" );
  17.  }
  18.  else
  19.   strcpy(t[i],chaine); // On copie la chaine "chaine" dans t[i]
  20.    }
  21. }
  22. void affichage(char **t,int nb) // Fonction d'affichage du tableau
  23. {
  24. int i;
  25. for (i=0;i<nb;i++)
  26. {
  27.      printf("\n Chaine %d : %s  \n",i,t[i]);
  28. }
  29. }
  30. void permut(char** ch1,char** ch2) // Fonction permutation
  31.       {
  32.           char *temp;
  33.           temp=(*ch1);
  34.           *ch1=(*ch2);
  35.           *ch2=temp;
  36.       }
  37. void tri(char **t,int nb) //Fonction de tri des chaînes
  38. {
  39.      int i,rep=0;
  40.    
  41.      do
  42.      {
  43.         for (i=0;i<nb;i++)
  44.         {
  45.             if (strcmp(t[i],t[i + 1])>0)
  46.             {
  47.                permut(&t[i],&t[i+1]);
  48.                rep=1;
  49.             }
  50.         }
  51.      }while (rep=1);
  52.          
  53. }
  54. void clean(char **t, int nb)
  55.       {
  56.           int i;
  57.           if (t == NULL)
  58.              return;
  59.            
  60.           for (i=0; i < nb; i++)
  61.           {
  62.               if (t[i])
  63.                 free(t[i]);
  64.           }
  65.           free(t);
  66.       }
  67. int main()
  68. {
  69.    
  70. char **t;
  71. int nb;
  72. do//Saisie protégée du nombre de chaînes de caractères
  73.        printf("Veuillez saisir le nombre de chaines de caracteres a traiter : (entre 1 et 15)\n" );
  74.    scanf("%d",&nb);
  75.    getchar();
  76. }while(nb<1||nb>15);
  77. t=(char**)malloc(nb * sizeof (char*));
  78. if(t==NULL)
  79.  {
  80.             printf("Pas assez de memoire" );
  81.  }
  82. //Allocation dynamique de l'espace nécessaire pour stocker un tableau de nb pointeurs sur des chaînes de caractères
  83. saisi(t,nb); //Fonction de saisie des chaînes de caractères
  84. printf("\nChaines de caracteres initiales\n" );
  85. affichage(t,nb);//Fonction d'affichage des chaînes de caractères
  86. tri(t,nb); //Fonction de tri des chaînes de caractères
  87. printf("\nChaines de caracteres apres le tri : \n" );
  88. affichage(t,nb);//Fonction d'affichage des chaînes de caractères
  89. clean(t,nb);//Fonction de libération de la mémoire
  90. system("pause" );
  91. return 0;
  92. }

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 16:56:26
n°1275036
Sve@r
Posté le 30-12-2005 à 17:41:16  profilanswer
 

snipred a écrit :

Bon j'en suis arrivé là mais y'a encore un peu de chemin...
En tout cas, il n'y a plus d'erreurs...
Mais ça ne marche pas pour autant...


 
while (rep=1); => Classique => A mon avis il ne s'arrête jamais ton prog !!!
 
Par ailleurs, l'algo du tri à bulle demande soit qu'on commence au premier élément et qu'on s'arrête à l'avant dernier parce qu'on va comparer l'élément "i" avec l'élément "i + 1"; soit on commence au second élément et on s'arrête au dernier parce qu'on compare l'élément "i - 1" avec l'élément "i".
Toi, tu commences au premier élément (i=0) et tu t'arrêtes au dernier élément (i < nb) => A ton avis, quand tu seras au dernier élément "t[nb - 1]" et que tu le compareras avec le suivant "t[nb]" qui est hors des limites du tableau, que va-t-il se passer ???
 
Dernier truc => si "t" est nul, après le malloc initial, faut pas continuer parce que ça peut pas marcher => exit(-1) ou return(-1) au choix


Message édité par Sve@r le 30-12-2005 à 17:55:02
n°1275046
snipred
Posté le 30-12-2005 à 17:53:12  profilanswer
 

En effet, j'ai corrigé et mis :
 

Code :
  1. while (rep!=1)


 
Cependant quand je lance le programme j'ai ceci :
(ma permutation cloche...)
 

Citation :

Veuillez saisir le nombre de chaines de caracteres a traiter : (entre 1 et 15)
2
Veuillez saisir la chaine de caracteres 1 :
zzz
Veuillez saisir la chaine de caracteres 2 :
aaa
 
Chaines de caracteres initiales :
 Chaine 0 : zzz
 Chaine 1 : aaa
 
Chaines de caracteres apres le tri :
 Chaine 0 : aaa
 Chaine 1 :
Appuyez sur une touche pour continuer...


 
Et pout 3 chaînes le programme plante...

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 17:56:43
n°1275076
snipred
Posté le 30-12-2005 à 18:20:54  profilanswer
 

je dois partir mais je reviendrai ^^ demain
 
Je veux te remercier pour ta patience hors du commum !

Message cité 1 fois
Message édité par snipred le 30-12-2005 à 18:21:20
n°1275108
Sve@r
Posté le 30-12-2005 à 19:04:37  profilanswer
 

snipred a écrit :

En effet, j'ai corrigé et mis :
 

Code :
  1. while (rep!=1)



Bon, manifestement tu comprends pas l'algo du tri à bulle
 
Le tri à bulle part du principe qu'on compare chaque élément avec le suivant (ou le précédent, c'est pareil). Et si les deux éléments ne sont pas à la bonne place l'un par rapport à l'autre, alors ont les permute.
Mais ce n'est pas parce qu'ils ont été permutés qu'ils sont maintenant à la bonne place. Imagine que tu as "D A E C"; tu compares "D" avec "A" et tu les permutes => tu obtiens "A D E C" mais c'est toujours pas bon.
Donc, pour que le tri se fasse, il faut recommencer le balayage de l'ensemble du tableau tant qu'on a eu au-moins une permutation. Ce n'est que si l'ensemble du tableau est balayé sans une seule permutation qu'on a un tableau correctement trié.  
Avec cet algo, les éléments les plus légers remontent lentement le long du tableau comme des bulles => d'où le nom "tri à bulle".
 
On peut l'optimiser un peu l'algo en mémorisant, à chaque boucle, la position de la première permutation et en recommençant seulement à partir de ce point (tous les éléments situés avant étant déjà triés) lors de la boucle suivante => d'où le nom de "tri à bulle optimisé".
 
Avec ton "while (rep != 1)" tu arrêtes ta boucle à la première permutation et si, par (mal)chance, il n'y a aucune permutation dès le départ alors tu boucleras indéfiniment !!!
 

snipred a écrit :

Je veux te remercier pour ta patience hors du commum !


J'accepte tes hommages car ils me sont dûs  :D  :D  :D  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1275235
snipred
Posté le 31-12-2005 à 09:31:27  profilanswer
 

Voilà ma réponse bien que je trouve que c'est pas très optimisé :
 

Code :
  1. void tri(char **t,int nb) //Fonction de tri des chaînes de caractères
  2. {
  3.      int i,rep=0;
  4.    
  5.      do
  6.      {
  7.         for (i=0;i<nb-1;i++)
  8.         {
  9.             if (strcmp(t[i],t[i+1])>0)
  10.             {
  11.                permut(&t[i],&t[i+1]);
  12.             }
  13.         }
  14.         rep=rep+1;
  15.      }while (rep<nb); 
  16. }

Message cité 1 fois
Message édité par snipred le 31-12-2005 à 09:34:59
n°1275239
Emmanuel D​elahaye
C is a sharp tool
Posté le 31-12-2005 à 10:08:07  profilanswer
 

snipred a écrit :

Excusez-moi, je pensais que c'était du C++ car c'est ce que j'apprends en C++.


Citation :

Code :
  1. #include<stdio.h>



Arf, si c'est du C++, il date du siècle dernier. Depuis 1998, on écrit

Code :
  1. #include<cstdio>


Si ta prof ne sait pas ça, change d'école et fait toi rembourser...


Message édité par Emmanuel Delahaye le 31-12-2005 à 10:15:29

---------------
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/
n°1275242
Emmanuel D​elahaye
C is a sharp tool
Posté le 31-12-2005 à 10:13:38  profilanswer
 

Sve@r a écrit :

Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ???
Au pire caste le => t=(char**)malloc(nb *sizeof(char*));


Non. Le bon conseil est "vérifie que ton compilateur est bien C et on C++". L'extension du source doit être ".c" et non ".cpp" ni ".C".


---------------
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/
n°1275247
Sve@r
Posté le 31-12-2005 à 11:02:58  profilanswer
 

snipred a écrit :

Voilà ma réponse bien que je trouve que c'est pas très optimisé :
 

Code :
  1. void tri(char **t,int nb) //Fonction de tri des chaînes de caractères
  2. {
  3.      int i,rep=0;
  4.    
  5.      do
  6.      {
  7.         for (i=0;i<nb-1;i++)
  8.         {
  9.             if (strcmp(t[i],t[i+1])>0)
  10.             {
  11.                permut(&t[i],&t[i+1]);
  12.             }
  13.         }
  14.         rep=rep+1;
  15.      }while (rep<nb); 
  16. }



 
Amusant ce "while (rep < nb)" mais tu as raison, ce n'est pas optimisé. Car s'il n'y a qu'une seule permutation à faire pour que le tableau soit correctement trié, ta fonction fera quand-même "nb" balayages.
 
Autre chose: ta boucle "for (i=0; i < nb -1; i++)" fera l'opération "nb  - 1" à chaque itération => perte de temps. L'algo fonctionnera aussi si tu fais "for (i=1; i < nb; i++)" et que tu compares "t[i]" avec "t[i - 1]" et sera un poil plus rapide...


Message édité par Sve@r le 31-12-2005 à 11:06:32
n°1275265
snipred
Posté le 31-12-2005 à 12:04:42  profilanswer
 

Comme ceci :  
 

Code :
  1. void tri(char **t,int nb) //Fonction de tri des chaînes de caractères
  2. {
  3.      int i,rep=0;
  4.    
  5.      do
  6.      {
  7.         for (i=1;i<nb;i++)
  8.         {
  9.             if (strcmp(t[i],t[i-1])<0)
  10.             {
  11.                permut(&t[i],&t[i-1]);
  12.             }
  13.         }
  14.         rep=rep+1;
  15.      }while (rep<nb); 
  16. }


 
Cependant, je viens de m'apercevoir que si on met une chaine vide "  ", le programme tourne quand même et considère le vide comme étant avant le a, est-ce grave (docteur^^)?


---------------
Athlon 3500+ Core Venice/Asustek A8N SLI PRENIUM/DD Seagate 160 Go 8 Mo de cache/Leadtek 6600GT 128Mo/Creative Audigy 2 ZS/2X512 Mo Corsair Value PC 3200/Hiper Type R 480 W/Boitier Textorm 974MB
n°1275334
Sve@r
Posté le 31-12-2005 à 15:21:15  profilanswer
 

snipred a écrit :

Comme ceci :  
 

Code :
  1. void tri(char **t,int nb) //Fonction de tri des chaînes de caractères
  2. {
  3.      int i,rep=0;
  4.    
  5.      do
  6.      {
  7.         for (i=1;i<nb;i++)
  8.         {
  9.             if (strcmp(t[i],t[i-1])<0)
  10.             {
  11.                permut(&t[i],&t[i-1]);
  12.             }
  13.         }
  14.         rep=rep+1;
  15.      }while (rep<nb); 
  16. }


 
Cependant, je viens de m'apercevoir que si on met une chaine vide "  ", le programme tourne quand même et considère le vide comme étant avant le a, est-ce grave (docteur^^)?


 
Le caractère 'espace' a pour valeur ascii '0x20'
Le caractère 'a' a pour valeur ascii '0x61'
0x20 étant plus petit que 0x61, la chaîne "espace" est considérée comme étant avant la chaîne "a" => normal => si ça te gène faut que tu écrives ton propre "strcmp" ou que tu gères la saisie
 
PS: "while (rep < nb)" vraiment pas top. Déjà ce serait mieux écrit avec une boucle "for" mais avec cet algo, tu fais à chaque fois "nb" balayages alors qu'avec le vrai algo du tri à bulles tu peux n'en faire qu'un seul...

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Problème sur un exo de C [RESOLU]

 

Sujets relatifs
[Resolu] DataGrid colonne actuelleProblème d'écriture XML
probleme avec SmartyPetit probleme php de traitement de chaine (string) assez basic
[swing] Problème avec paintComponent sur un JPanel[ RESOLU ] Effacer des fichiers PDF qui ont plus d'une heure
[Resolu]Erreur à la fermeture de la balise HTMLprobleme aidez moi !!!!!!!!!!!!!!!
[Résolu] Probleme de mise en page 
Plus de sujets relatifs à : Problème sur un exo de C [RESOLU]


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR