Problème sur un exo de C [RESOLU] - C - Programmation
Marsh Posté le 29-12-2005 à 18:35:34
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.
Marsh Posté le 29-12-2005 à 18:40:17
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 ?
Marsh Posté le 29-12-2005 à 19:16:55
Je l'ai change de cat. A toi d'editer le titre.
A+,
Marsh Posté le 29-12-2005 à 20:51:26
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 :
|
EDIT : je viens de voir que c'est ton prof qui te demande d'utiliser gets().
Je demande une lapidation sur la place publique.
Marsh Posté le 30-12-2005 à 10:21:50
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 :
|
Marsh Posté le 30-12-2005 à 10:43:14
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 ?
|
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 :
|
C'est pour un caractère.
Ceci :
Code :
|
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 :
|
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] |
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.
Extrapolons au char*** :
|
(remarque : c'est une "notation" symbolique, ce n'est pas du C)
Marsh Posté le 30-12-2005 à 11:15:09
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 :
|
Apparemment j'ai rien compris
Citation : |
C'est là que je comprends pas trop...
Je suis vraiment désolé d'être aussi nul...
Marsh Posté le 30-12-2005 à 11:21:53
snipred a écrit :
|
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 :
|
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)
Marsh Posté le 30-12-2005 à 12:14:40
mais ca existe vraiment des "profs" comme ca ?
Marsh Posté le 30-12-2005 à 12:49:20
snipred a écrit : Je mets ici ce que j'ai déjà fait :
|
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 :
|
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 ?
|
Bon, cette fonction doit permuter des pointeurs sur des chaînes de caractères et non des pointeurs de pointeurs
Code :
|
snipred a écrit : J'ai déjà fait des bases pour mes fonctions mais sont-elles justes ?
|
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)
Marsh Posté le 30-12-2005 à 13:33:43
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: |
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]?
Marsh Posté le 30-12-2005 à 13:50:36
snipred a écrit : Merci beaucoup de ton aide ! |
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 :
|
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...
Marsh Posté le 30-12-2005 à 14:12:43
Citation : Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ??? |
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 :
|
Autre question, ceci devient inutile avec la fonction clean ?
Code :
|
Marsh Posté le 30-12-2005 à 14:22:44
Pour le cast, tu dois utiliser un compilateur obsolète... comme ton cours.
Au pif : Borland Turbo C ?
Marsh Posté le 30-12-2005 à 15:29:47
snipred a écrit :
|
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:
|
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
|
snipred a écrit : Autre question, ceci devient inutile avec la fonction clean ?
|
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. |
Marsh Posté le 30-12-2005 à 16:22:26
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 :
|
Marsh Posté le 30-12-2005 à 17:41:16
snipred a écrit : Bon j'en suis arrivé là mais y'a encore un peu de chemin... |
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
Marsh Posté le 30-12-2005 à 17:53:12
En effet, j'ai corrigé et mis :
Code :
|
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) |
Et pout 3 chaînes le programme plante...
Marsh Posté le 30-12-2005 à 18:20:54
je dois partir mais je reviendrai ^^ demain
Je veux te remercier pour ta patience hors du commum !
Marsh Posté le 30-12-2005 à 19:04:37
snipred a écrit : En effet, j'ai corrigé et mis :
|
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
Marsh Posté le 31-12-2005 à 09:31:27
Voilà ma réponse bien que je trouve que c'est pas très optimisé :
Code :
|
Marsh Posté le 31-12-2005 à 10:08:07
snipred a écrit : Excusez-moi, je pensais que c'était du C++ car c'est ce que j'apprends en C++. |
Citation :
|
Arf, si c'est du C++, il date du siècle dernier. Depuis 1998, on écrit
Code :
|
Si ta prof ne sait pas ça, change d'école et fait toi rembourser...
Marsh Posté le 31-12-2005 à 10:13:38
Sve@r a écrit : Bizarre... malloc est de type "void*" donc il devrait s'adapter tout seul. T'as bien inclus "stdlib.h" ??? |
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".
Marsh Posté le 31-12-2005 à 11:02:58
snipred a écrit : Voilà ma réponse bien que je trouve que c'est pas très optimisé :
|
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...
Marsh Posté le 31-12-2005 à 12:04:42
Comme ceci :
Code :
|
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^^)?
Marsh Posté le 31-12-2005 à 15:21:15
snipred a écrit : Comme ceci :
|
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...
Marsh Posté le 29-12-2005 à 18:16:07
Bonjour,
J'ai un problème avec cet exo :
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 !
Je mets ici ce que j'ai déjà fait :
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