Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ecrire en debut de ligne a chaque fois

Sujet résolu
    12 février 2023 à 20:15:24

    Bonsoir

    J'ai une liste chainee d'entiers:

    typedef struct chiffre
    {
        int _chiffre;
        struct chiffre *precedent;
    } Chiffre, *GrandEntier;

    A l'affichage j'utilise cette fonction:

    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.

    • Partager sur Facebook
    • Partager sur Twitter
      12 février 2023 à 21:25:58

      bonsoir

      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 …» …

      -
      Edité par White Crow 12 février 2023 à 21:28:31

      • Partager sur Facebook
      • Partager sur Twitter
        12 février 2023 à 21:48:38

        Merci, je pensais pas bien...

        >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.

        >ne cache jamais un pointeur avec un typedef

        Je viens de faire une recherche([Résolu] Initialiser un pointeur structure typedef - Et discours sur le C, l'abstraction, l'encapsulation, inline vs macros - page 1 - OpenClassrooms). Si le probleme est juste pour la comprehension alors je peux garder mon code actuel sinon je vais me retrouver avec des ** et * un peu partout et ca peut m'embrouiller. Si ca peut engendrer d'autres problemes alors je voudrai bien les connaitre

        >utiliser un autre design pour avoir une récursivité terminale serait peut-être une bonne idée

        J'ai pas compris ceci...

        • Partager sur Facebook
        • Partager sur Twitter
          12 février 2023 à 22:01:22

          Asmitta a écrit:

          Merci, je pensais pas bien... [...]

          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 … 

          Asmitta a écrit:

          [...]

          >ne cache jamais un pointeur avec un typedef

          Je viens de faire une recherche([Résolu] Initialiser un pointeur structure typedef - Et discours sur le C, l'abstraction, l'encapsulation, inline vs macros - page 1 - OpenClassrooms). Si le probleme est juste pour la comprehension alors je peux garder mon code actuel sinon je vais me retrouver avec des ** et * un peu partout et ca peut m'embrouiller. Si ca peut engendrer d'autres problemes alors je voudrai bien les connaitre

          [...]

          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 ?









          • Partager sur Facebook
          • Partager sur Twitter
            12 février 2023 à 22:08:19

            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 ...

            Tu marques encore un point merci

            • Partager sur Facebook
            • Partager sur Twitter
              12 février 2023 à 23:19:38

              Si on cherche l'efficacité, on ne va certainement pas représenter un grand nombre par une liste chaînée d'entiers , mais par un tableau dynamique.

              • Ça prendra moins de place (beaucoup)
              • L'accès sera direct, et plus rapide.

              Et comme l'accès est direct, le code est plus simple, on traite le tableau à l'endroit où à l'envers sans avoir à passer par une récursivité.

              -
              Edité par michelbillaud 12 février 2023 à 23:21:53

              • Partager sur Facebook
              • Partager sur Twitter
                13 février 2023 à 0:07:51

                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 😐

                • Partager sur Facebook
                • Partager sur Twitter
                  13 février 2023 à 1:56:11

                  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)
                   
                  void reverse(List *list) {
                      Node *current = list->first;
                      backward = NULL;
                      while(current) {
                          Node *forward = current->next;
                          current->next = backward;
                          backward = current;
                          current = forward;
                      }
                      list->first = backward;
                  }
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Le Tout est souvent plus grand que la somme de ses parties.

                    13 février 2023 à 3:52:39

                    Merci mais je voulais pas inverser ma liste...

                    • Partager sur Facebook
                    • Partager sur Twitter
                      13 février 2023 à 5:25:08

                      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.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                        13 février 2023 à 8:35:31

                        Asmitta a écrit:

                        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

                        • Partager sur Facebook
                        • Partager sur Twitter
                          13 février 2023 à 8:48:47

                          >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.

                          Je pense comprendre ton approche avec les tableaux dynamiques(cf L'allocation dynamique - Le langage C • Tutoriels • Zeste de Savoir ) et oui c'est pas ce que j'avais fait.

                          Je vais refaire l'exercice avec cette methode.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            13 février 2023 à 13:54:08

                            Asmitta a écrit:

                            >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.

                            Je pense comprendre ton approche avec les tableaux dynamiques(cf L'allocation dynamique - Le langage C • Tutoriels • Zeste de Savoir ) et oui c'est pas ce que j'avais fait.

                            Je vais refaire l'exercice avec cette methode.

                            Le lien indiqué, c'est plutôt les VLA (Variable length arrays) qui ne sont pas extensibles.

                            Voir plutôt

                            https://www.mbillaud.fr/docs/Pointeurs/pointeurs.html#une-application-de-lallocation-dynamique-un-tableau-extensible


                            Des tableaux qui sont

                            • alloués dynamiquement
                            • ré-alloués quand on veut y ajouter des trucs et qu'il n'y a plus de place
                            • Partager sur Facebook
                            • Partager sur Twitter

                            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.
                            • Editeur
                            • Markdown