谁能解释为什么此递归输入函数正确?我无法手动跟踪或找出原因

时间:2019-05-10 18:35:28

标签: c++

假设我有:

int main ()
{
    message(3);
    return 0;
}

void message (int times)
{
    cout < "Message " << times << ".\n";
    if (times > 0)
    {
        message(times - 1);
    }
    cout << "Message " << times << " is returning. \n";
}

输出为:

Message 3
Message 2
Message 1
Message 0
Message 0 is returning.
Message 1 is returning.
Message 2 is returning.
Message 3 is returning.

我只是不明白为什么我得到消息1-3在输出中返回。我可以理解进入Message 0 is returning(因为Times一次又一次地减去1,直到它不满足if语句,然后跳到底部cout语句)

但是Times应该保持为0。我不知道它如何又回到值1、2和3。魔术!

4 个答案:

答案 0 :(得分:7)

如果您替换了每个message()呼叫,并且呼叫的内容很明显

void message()
{
    cout << "Message " << 3 << ".\n";
    {
        cout << "Message " << 2 << ".\n";
        {
            cout << "Message " << 1 << ".\n";
            {
                cout << "Message " << 0 << ".\n";
                cout << "Message " << 0 << " is returning. \n
            }
            cout << "Message " << 1 << " is returning. \n
        }
        cout << "Message " << 2 << " is returning. \n
    }
    cout << "Message " << 3 << " is returning. \n";
}

每次调用message()都会始终显示返回消息。

解决方案: 要获得描述您在times == 0时仅打印“ returning”消息的位置的行为,您需要将returning cout放在else分支中,如下所示

int main ()
{
    message(3);
    return 0;
}

void message (int times)
{
    cout < "Message " << times << ".\n";
    if (times > 0)
    {
        message(times - 1);
    }
    else
    {
        cout << "Message " << times << " is returning. \n";
    }
}

答案 1 :(得分:6)

您正在通过副本传递times,因此每个呼叫中​​的时间值永远不会改变。例如,如果times3,则您进行cout < "Message " << times << ".\n";会得到3,然后调用message(times - 1),将其赋予2(但{{1 }}保留为times),然后运行3。由于cout << "Message " << times << " is returning. \n";仍然是times,因为您从未更改过它,所以您可以打印3

如果改为改为通过引用获取函数,则每个递归调用都将修改相同的变量,并获得您认为会得到的输出。看起来像

3

答案 2 :(得分:2)

让我们只看最外层的调用,即进行一些小的修改:

/usr/local/lib/pkgconfig

这将产生输出:

int main ()
{
    message(3);
    return 0;
}

void message (int times)
{
    cout < "Message " << times << ".\n";
    if (times > 0)
    {
        std::cout << "recurse here \n";
    }
    cout << "Message " << times << " is returning. \n";
}

接下来,考虑

Message 3
recurse here
Message 3 is returning.

将不会更改message(n-1); 的值。因此,如果我们回到完整的示例,则只需在输出中将n替换为recurse here ...的输出,而message(2)的输出将以相同的方式包含message(2)的输出在中间。

答案 3 :(得分:0)

对于所需的输出,最后的cout语句应放在if块内。 现在,为什么返回消息1-3的原因是因为每次调用该函数时,都会执行整个函数。这并不意味着函数执行会在您进行递归调用的地方停止。由于您的函数返回void,因此每次递归都返回void并继续执行其余的过程。 让我们分解一下: 你从3开始 它打印Message 3并以(2)作为参数调用相同的函数。 这将打印出Message 2,然后以(1)作为参数调用该函数 这将打印Message 1并使用(0)作为参数进行下一个函数调用。 这会打印Message 0,这是有趣的地方。最终if条件为false,函数到达最后一行并打印Message 0 is returning。 现在使用(0) returns void and control goes to function called with(1)as argument. It reaches the bottom and prints消息1返回. Now, this function again returns void and control goes to the previous call with argument (2) and prints消息2返回and this function returns void again and then control goes back to the outermost, first function call which was made in main()That function too reaches the end and prints out消息3返回and returns void to main() The short answer to this is EVERY function whether be called through recursion or not, runs till the encounters a return`语句。对于void函数,它将一直持续到最后。 还要记住,递归调用之后函数主体中的每个语句都从最里面的调用到最外面的调用以相反的顺序执行。从最外层调用到最内层调用将执行上面所有内容。