-1
votes

Pourquoi la boucle de sortie 3, boucle 2, boucle 1, boucle 1?

Pour le code suivant, je m'attendais à la console de générer xxx pré>

Cependant, p> xxx pré>

est affiché. Je comprends que c'est une méthode récursive, c'est-à-dire appeler. Juste en difficulté pour comprendre comment ça marche. Ceci est une question d'examen que j'ai lutté avec. P>

J'ai essayé de déboguer et je vois que les suivants se produisent: P>

  1. Après que je tire à 0, il sort de la boucle tandis que prévu li>
  2. Il exécute les lemmings de retour - 1; Déclaration à laquelle j'aurais pensé que Lemmings équivaut à -1, mais cela remonte à la ligne I = Writetoconsole (I - 1); qui est exécuté li>
  3. Quelques Lemmings = 1 et I = -1 li>
  4. Il continue mais je suis perdu à ce point li> OL>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WhileLoopExample
    {
        class Program
        {
            private static int WriteToConsole(int Lemmings)
            {
                int i = Lemmings;
                while (i > 0)
                {
                    Console.WriteLine("loop {0}", i);
                    i = WriteToConsole(i - 1);
                }
                return Lemmings - 1;
            }
    
            static void Main(string[] args)
            {
                WriteToConsole(3);
                Console.ReadKey();
            }
        }
    }
    


2 commentaires

Vous mélangez la récursion avec l'itération. La durée de votre itération (nombre d'itérations de boucle) dépend de la valeur Lemming donnée ainsi que de la valeur de retour de Writetoconsole. Toutefois, la valeur de retour de Writetoconsole elle-même ne dépend pas d'appels récursifs d'écrans de circulation, mais uniquement sur l'argument de Lemmings qui n'est pas modifié dans la méthode. Peut-être que ce sera plus facile pour vous de comprendre si vous dessinez le flux de votre programme sur papier comme organigramme ....


Vous n'êtes pas obligé de descendre ce trou de lapin très profond pour voir ce qui se passe. Il suffit de regarder lorsque vous appelez Writetoconsole la première fois avec Lemmings = 3. Maintenant, le premier appel récursif de Writetoconsole aura son argument de Lemmings défini sur 2, ce qui en résulte renvoyant la valeur 1 . Essayez de comprendre cela. Maintenant, tandis que l'appel récursif de Writetoconsole (et d'autres appels récursifs davement dans le trou de lapin) Imprimez «boucle 2» et «boucle 1», la valeur de retour de 1 pour les tout premiers causes d'appel récursif une copie supplémentaire de "boucle 1".


4 Réponses :


1
votes

C'est parce que vous avez une boucle et em> vous avez une récursion. Vous devez vous débarrasser de l'appel à Writetoconsole (I) Code> Intérieur Writetoconsole CODE> ou Débarrassez-vous de la boucle et collez-vous avec une récursion.

De plus, vous utilisez la valeur de retour. de l'appel récursif pour influencer i code> et donc votre pendant code> boucle. Je pense que cela provoque la principale affaire de votre confusion. P>

Heureusement, ce n'est que quelques étapes, afin que cela puisse être décomposé assez facilement. C'est ce qui se passe. La boucle tandis que la boucle est impliquée, je décris simplement la sortie, les modifications des appels i et les appels récursifs. P>

You call WriteToConsole(3); // Let's call this 'instance' of the function call 'A'
  A prints "Loop 3"
  A calls WriteToConsole(2); // Let's call this 'B'
    B prints "Loop 2"
    B calls WriteToConsole(1) // Let's call this 'C'
      C prints "Loop 1"
      C calls WriteToConsole(0); // Let's call this 'D'
        D doesn't enter it's loop. 
        D returns -1 (Lemmings - 1, where Lemmings is 0), i becomes -1 in C
      C's loop ends because i is -1
      C returns 0, i becomes 0 in B
    B's loop ends, because i is 0
    B returns 1, i becomes 1 in A
  A is still in the loop, since its 'i' > 0, so..
  A prints "Loop 1" (again)
  A calls WriteToConsole(0); // Let's call this 'E'
    E returns -1, i becomes -1 in A
  A returns 2, this value is ignored in your main function.
End of program


1 commentaires

Merci, votre réponse est vraiment utile. Surtout avec les lettres et l'indentation. Je comprends maintenant beaucoup mieux



0
votes

Pour réaliser ce que vous voulez, dans ce cas, vous avez besoin une boucle d'une boucle ou un autre mécanisme d'itération strong>, soit au moyen de la récursivité (sans pendant code>) ou au moyen de A pendant code> (mais ensuite sans récursion).

Voici la solution pour le pendant code> sans récursion: p>

private static void WriteToConsole(int Lemmings)
{
    int i = Lemmings;
    while (i > 0)
    {
        Console.WriteLine("loop {0}", i);
        i = i - 1; // Decrease i, no need for recursion here
    }
}


2 commentaires

Ce n'était pas moi, je jure ;-)


Merci d'avoir répondu Peter, c'est une question d'examen. J'ai maintenant mis à jour le poste.



2
votes

Dans votre appel récursif, vous passez dans i - 1 . Cela devient lemmings - que vous revenez comme lemmings - 1 .

Il y a deux -1 s se passe - est-ce ce que vous voulez?

Mais si vous regardez ce qui se passe:

  • Le premier appel a lemmings comme 3 et i comme 3 . . .

    boucle 3 est écrit.

    Puis la récursion arrive, passant dans 3-1 :

    • Le deuxième appel a lemmings comme 2 et i comme 2 . . .

      boucle 2 est écrit.

      La récursivité se produit, passant dans 2-1 :

      • Le troisième appel a lemmings comme 1 et i comme 1 . . .

        boucle 1 est écrit.

        Puis la récursion arrive, passant dans 1-1 :

        • Le quatrième appel a lemmings comme 0 et i comme 0 . .

          Le pendant n'est pas entré, donc 0-1 est retourné.

        • retour à l'intérieur du troisième appel:

          i est attribué -1 , donc le moment se termine.

          Le troisième appel renvoie 1-1 .

        • retour à l'intérieur du deuxième appel:

          i est attribué 0 , de sorte que le moment se termine.

          Le deuxième appel renvoie 2-1 .

        • retour à l'intérieur du premier appel:

          i est attribué 1 , donc le moment continue.

          boucle 1 est écrit.

          L'exécution continue d'ici, mais tout sans sortie. Ce qui précède est la raison pour laquelle vous obtenez deux boucle 1 s.


0 commentaires

3
votes

Votre problème est que vous ne comprenez pas la notion d'activation de la fonction . Chaque activation de la fonction a sa propre copie de i et sa propre copie de lemmings , ce qui sont complètement indépendants de toutes les autres fonctions.

Qu'est-ce qui vous gâte ici est que vous avez cinq - oui cinq - des appels différents vers Writetoconsole , et tous ont leur propre < / em> copie de i et leur copie copie de lemmings . Illustrons que, en instrumenté votre programme pour montrer chaque activation de fonction différente et quelles sont les valeurs de chaque variable à chaque point: xxx

Nous pouvons voir la sortie reflète ce qui se passe : xxx

lisez la trace très soigneusement jusqu'à ce que vous comprenez ce qui se passe. Vous obtenez quatre sorties de boucle x car l'appel numéro 1 est dans la boucle supérieure lorsque i est 3 et après l'appel récursif, I est 1. L'état de la boucle est rempli, appelez donc 1 imprime les deux Loop 3 et boucle 1 .


2 commentaires

Merci Eric. Votre réponse me permet de déboguer et de mieux comprendre cela. J'aurais dû clarifier, c'est une question d'examen que j'ai lutté avec. Impossible de trouver beaucoup sur le Web pour m'aider à comprendre, peut-être que je ne cherche pas la bonne chose (essayé et pendant des exemples de boucle). Beaucoup apprécient vos efforts et votre temps.


@Enzo: Droite, j'ai pensé que c'était probablement un problème de devoirs ou quelque chose comme ça; C'est pourquoi toutes les personnes qui vous ont dit "tu le fais mal" étaient inutiles. Vous êtes très bienvenu. La récursion peut être délicate à la raison de.