void afficher(GrandEntier G)
{
printf("\n");
while (G != NULL)
{
printf("%d", G->_chiffre);
G = G->precedent;
}
}
Mais les elements sont dans l'ordre inverse du sens de lecture "normal". Pour afficher donc normalement j'utilisais le retour chariot(\r) mais ca ne sert a rien car a chaqie fois ca ecrase ce qui est la. Comment faire pour ecrire en debut de ligne a chaque fois, par au dessus mais genre inserer un nouveau chiffre en tete de ligne a chaque fois ?
je precise que j'evite l'inversion de la liste, ou transformer ma liste en une liste doublement chainee, je cherche une autre solution.
ta question : « Comment faire pour ecrire en debut de ligne a chaque fois, par au dessus mais genre inserer un nouveau chiffre en tete de ligne a chaque fois ?» est un problème XY.
Tu sais comment afficher des chiffres mais pas dans le bon sens, alors tu essayes d'écrire avant ce que tu viens d'écrire … mauvaise question. La bonne question est : «comment afficher tout dans l'ordre que je désire ?».
Là la réponse est simple : tu as une structure récursive alors pense récursivement. Pour représenter le nombre "123456" tu as une structure du genre "⑥→⑤→④→③→②→①→NULL". Donc avant d'afficher le "6" il faut d'abord afficher la suite et ensuite le "6". Si tu traduis cela en C cela donne :
void afficher(GrandEntier G)
{
// Si on a quelque chose à afficher
if (G) {
// on affiche d'abord la suite
afficher(G->precedent);
// puis le chiffre
printf("%d", G->_chiffre);
}
}
C'est ce qui est le plus simple à faire avec ton design. Ensuite ne t’embarrasse pas des remarques «la récursivité c'est pas bien/efficace.…». En revanche soucie-toi des remarques comme «ne cache jamais un pointeur avec un typedef», «n'hésite pas à faire des recherches avec google», «utiliser un autre design pour avoir une récursivité terminale serait peut-être une bonne idée …» …
Oui mais ca resout mon probleme sans avoir a inverser ma liste ou la transformer en liste doublement chainee donc ca me va la. Mon objectif ici c'est de resoudre juste l'exo, merci quand meme pour le rappel sur le cote non-optimal de cette approche.
Mais sans doute n'as-tu pas encore le réflexe de penser ainsi … ça viendra.
Asmitta a écrit:
[...]
>la récursivité c'est pas bien/efficace.…
Oui mais ca resout mon probleme sans avoir a inverser ma liste ou la transformer en liste doublement chainee donc ca me va la. Mon objectif ici c'est de resoudre juste l'exo, merci quand meme pour le rappel sur le cote non-optimal de cette approche. [...]
C'est bien pour cela que je te dis de ne pas t'en préoccuper si jamais cela t'es lancé à la face. Les compilos sont de plus en plus capable d'en tirer le meilleur profit, et si c'est pour simuler une pile …
Je suppose qu'avec le temps tu apprendras que relire un code qui n'est pas lisible est une tâche fastidieuse. Cela peut-être autant un de tes codes anciens qu'un code écrit par un autre. Si tu caches un pointeur dans un typedef, il n'y a rien à la lecture qui te permettra de savoir rapidement qu'il s'agit d'un pointeur plutôt qu'une struct … si tu as une étoile tu sais d'office que c'est un pointeur et pas autre chose. Les * n'embrouillent pas, elles rendent un code plus lisible ; et si tu as une flopée d'étoiles alors c'est que tu dois sérieusement penser à refactorer ton code.
Asmitta a écrit:
[...]
>utiliser un autre design pour avoir une récursivité terminale serait peut-être une bonne idée
J'ai pas compris ceci...
Tu l'apprendras sans doute par la suite dans ton cours. Une fonction récursive terminale est une fonction dont la dernière action est soit de renvoyer une valeur sans avoir fait d'appel récursif, soit de faire un appel récursif. Ce genre de fonction est très lisible, se dérécursive aisément avec une boucle; c'est d'ailleurs tellement aisé que les compilos modernes le font tout seul (si tu demandes une optimisation). Alors pourquoi le faire soi-même ?
Je connaissais le dernier point, mais pas le terme "terminal". Merci
>Je suppose qu'avec le temps tu apprendras que relire un code qui n'est pas lisible est une tâche fastidieuse. Cela peut-être autant un de tes codes anciens qu'un code écrit par un autre ...
A l'examen j'ai utilisé un tableau, sûrement pas celui auquel tu fais allusion vu la note que j'ai eu.
Les correcteurs ont proposés cette structure comme potentielle solution et moi je trouve aussi que ça prendra beaucoup de place en mémoire mais j'y peux rien. Je fais maintenant ce qu'on me demande le cursus académique semble ne pas aimé l'innovation 😐
Le chiffre "précédent" est le "suivant" dans la liste chaînée. On peut facilement inverser une liste simplement chaînée sans récursivité: (à condition d'avoir un descripteur de liste)
Si on connaissait le nombre de maillons de la chaîne, on pourrait construire un tableau en mettant les nombres dans la partie la moins significative en premier. On ferait un malloc() d'abord et on lirait la chaîne ensuite.
Le Tout est souvent plus grand que la somme de ses parties.
A l'examen j'ai utilisé un tableau, sûrement pas celui auquel tu fais allusion vu la note que j'ai eu.
Les correcteurs ont proposés cette structure comme potentielle solution et moi je trouve aussi que ça prendra beaucoup de place en mémoire mais j'y peux rien. Je fais maintenant ce qu'on me demande le cursus académique semble ne pas aimé l'innovation 😐
Tu peux trouver ce que tu veux, mais la réalité c'est que pour une liste de n nombres chaînés, la taille occupée avec une liste c'est n fois celle d'un maillon qui contient
Un nombre (de 4 ou 8 octets)
Un pointeur vers le maillon suivant
Ce qui doit faire 16 ou 32 octets, contenu dans un bloc alloué de taille probablement minimum (genre 64 octets) parce que la charge utile est petite, plus l'overhead des données de gestion.
En résumé : 64 octets pour chaque entier de 8.
Le tableau, c'est n fois la taille d'un nombre, 2*n si on utilise la stratégie d'extension classique + 1 overhead (*). Donc 16 octets pour un entier.
Y a pas photo sur la différence de taille. Rapport 4.
Et il n'y a pas photo non plus sur
La simplicité du code
Ses performances.
Mais si l'exercice c'est "faites-le avec une liste chainée", c'est pour tester les compétences en matière de listes chaînées, et il faut effectivement faire ce qui est demandé, dans ce contexte. Même si ce n'est pas la meilleure facon de faire, et de loin.
Parce le correcteur, en voyant u tableau, il pense que le candidat
Ne sait pas lire un énoncé
Utilise un tableau comme contournement parce qu'il ne sait pas utiliser les pointeurs
Ce qui n'empêche pas de savoir qu'il y a de bien meilleures implémentations.
(*) qui donne un coût amorti constant pour l'opération d'ajout.
- Edité par michelbillaud 13 février 2023 à 8:53:20
>Mais si l'exercice c'est "faites-le avec une liste chainee", c'est pour tester les compétences en matière de listes chaînées, et il faut effectivement faire ce qui est demandé, dans ce contexte.
Rien n'a été précisé. On devais juste creer une structure GrandEntier et les methodes de calcul qui vont avec pour palier a la limite de taille du type int.
>Mais si l'exercice c'est "faites-le avec une liste chainee", c'est pour tester les compétences en matière de listes chaînées, et il faut effectivement faire ce qui est demandé, dans ce contexte.
Rien n'a été précisé. On devais juste creer une structure GrandEntier et les methodes de calcul qui vont avec pour palier a la limite de taille du type int.
ré-alloués quand on veut y ajouter des trucs et qu'il n'y a plus de place
Ecrire en debut de ligne a chaque fois
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.