首页 > 解决方案 > 递归函数内的多个返回语句

问题描述

我目前正在阅读 Steve Oualline 的“实用 C 编程第 3 版”。

目前我正在阅读关于递归的第 2 章,在本章中,作者提出了一个练习,读者必须尝试编写一个递归函数来计算一个数字在数组中出现的次数。

请考虑以下代码:

#include <stdio.h>

size_t count(const int [], size_t, int);

enum {ARRAY_LEN = 11};

int main()
{

    const int num_array[ARRAY_LEN] = {1, 2, 3, 4, 5, 5, 6, 7, 3, 9, 0};

    int number = 0;

    puts("Type a number: (0-9)");
    scanf("%d", &number);

    printf("Number of appearances: %lu\n", count(num_array, ARRAY_LEN, number));

    return 0;

}

size_t count(const int n_array[], size_t arr_len, int num)
{
    return arr_len == 0 ? 0 : ( n_array[arr_len - 1] == num ) + count( n_array, arr_len - 1, num );

}

我的问题是:

C 如何知道将哪个return带回主函数?因为,在这个例子中,我们有 3 个返回,并且它们都在某个时间它们的条件变为真,那么,C 怎么知道return 0;它必须退出递归函数而不是继续在函数内寻找另一个返回count()

谢谢。

标签: crecursionfunction-definition

解决方案


当你有递归函数调用时,你有一个函数的多个“实例”处于活动状态,相互调用和返回。为了形象化这一点,我发现想象一下,而不是在计算机上运行的 C 程序,你有一群人在一个房间里,你们都给他们一套相同的指令,然后你让他们开始,这很有用为您解决问题。对于您问题中的代码,它会是这样的。

你选择一个人说:“嘿,约翰,这是一个大小为 3 的数组: 。你能告诉我这个数字出现[1, 2, 3]了多少次吗?”2

约翰从你手中接过阵列,他看着他的指示。数组的大小不是 0,所以他不会告诉你 0。他数组的最后一个元素不是2,所以他也没有做第二件事。但是要做第三件事,他需要进行递归调用,所以他在房间里挑选了其他人,他说:“嘿,玛丽,这是一个大小为 2 的数组: 。你能告诉我这个数字出现[1, 2]了多少次吗?2在里面?”

玛丽从约翰那里接过阵列,她看着她的指示。数组的大小不是 0,所以她没有告诉 John 0。但是她数组的最后一个元素 2,所以她确实做了第二件事。但是要做第二件事,她还需要进行递归调用,所以她在房间里挑选了其他人,然后她说,“嘿,弗雷德,这是一个大小为 1 的数组:[1]。你能告诉我这个数字是多少次吗?2出现在里面?”

弗雷德看着他的指示。数组的大小不是 0,所以他没有告诉 Mary 0。他数组的最后一个元素不是2,所以他没有做第二件事。他也需要进行递归调用来做第三件事,所以他选择房间里的其他人说:“嘿,简,这是一个大小为 0 的数组: 。你能告诉我这个数字出现[]了多少次吗?2在里面?”

简看着她的数组,大小0。所以她说,“弗雷德,那个数组中出现的次数2是:0”。

这就是弗雷德所等待的。弗雷德正在写第三个return陈述,所以他从简那里听到的都是他的答案。2他说:“玛丽,该数组中出现的次数是:0”。

这就是玛丽所等待的。但她正在处理第二个return陈述,所以她从 Fred 那里听到的任何信息都加了 1。2她说,“约翰,该数组中出现的次数是:1”。

这就是约翰所等待的。约翰正在研究第三个return陈述,所以他从玛丽那里听到的一切都是他的答案。2他对你说,“该数组中出现的次数是:1”。

现在你有了答案!

我曾经教过一堂 C 编程课,有一天我给班上的每个人发了一份讲义,里面有一些关于如何递归、按顺序遍历二叉树的人类可读说明。然后我把一棵“二叉树”——一块硬纸板,上面排列着一堆树状结构的黄色便签——递给前排的一个随机学生,开始遍历。这是绝对的混乱,但也很有趣。(我想。 无论如何,认为这很有趣!)


推荐阅读