如何检测根递归调用?
Posted
技术标签:
【中文标题】如何检测根递归调用?【英文标题】:How to detect the root recursive call? 【发布时间】:2011-02-11 03:47:56 【问题描述】:假设我们正在编写一个简单的递归函数fib(n)
,它计算第n 个斐波那契数。现在,我们希望函数打印第 n 个数字。由于重复调用相同的函数,因此必须有一个条件,只允许根调用打印。问题是:如何在不传递任何额外参数或使用全局/静态变量的情况下编写此条件。
所以,我们正在处理这样的事情:
int fib(int n)
if(n <= 0) return 0;
int fn = 1;
if(n > 2) fn = fib(n-2) + fib(n-1);
if(???) cout << fn << endl;
return fn;
int main()
fib(5);
return 0;
我认为根调用不同于所有子调用,因为它返回到不同的调用者,即本例中的 main 方法。我想知道是否可以使用这个属性来写条件以及如何写。
更新:请注意,这是一个人为的示例,仅用于展示这个想法。从标签中应该可以清楚地看到这一点。我不是在寻找标准解决方案。谢谢。
【问题讨论】:
正如许多答案中所指出的,通常的做法是创建一个启动递归的包装函数。自定义前/后处理(如 IO)可以去那里。 【参考方案1】:我认为您可以从堆栈中获取返回地址,并以某种方式将其与 fib 函数的地址进行比较。返回地址应该靠近参数 n ,除非 n 在某个寄存器中传递,但在标准 C 中它不应该。您只需要知道返回地址相对于参数的位置。
【讨论】:
【参考方案2】:我这样做的方法是使用辅助函数:
int _fib(int n)
if(n <= 0) return 0;
int fn = 1;
if(n > 2) fn = _fib(n-2) + _fib(n-1);
return fn;
int fib(int n)
int fn=_fib(n);
cout << fn << endl;
return fn;
或者,你可以这样写(c++):
int fib(int n, bool f=true)
if(n <= 0) return 0;
int fn = 1;
if(n > 2) fn = fib(n-2, false) + fib(n-1, false);
if(f) cout << fn << endl;
return fn;
【讨论】:
不错的一个。我暂时忘记了默认参数。 顺便说一句,您的第一个解决方案不是打印所有内容吗?似乎函数 _fib 应该调用自己,而不是 fib。【参考方案3】:这里有一个棘手的方法,虽然我不确定这是否值得:):
int fib(int n)
// if(n <= 0) return 0;
int isRoot;
if ( n <= 0 )
isRoot = 1;
n = -n;
else isRoot = 0;
int fn = 1;
if(n > 2) fn = fib(n-2) + fib(n-1);
if(isRoot) cout << fn << endl;
return fn;
int main()
fib(-5);
return 0;
但是,该函数要求您并不是真的要发送负值:)。
【讨论】:
【参考方案4】:如果你真的想问 C 是否可以访问某种 API 以允许函数体中的代码找出调用执行函数的位置,答案是 否。。 p>
【讨论】:
没错,但是you(就像在程序员中一样)可以修饰调用以找出它们来自哪里。【参考方案5】:根递归调用是调用递归的点,即main
中的调用。鉴于此,您可以稍微重写您的代码(类似这样):
int fib(int n)
if(n <= 0) return 0;
int fn = 1;
if(n > 2) fn = fib(n-2) + fib(n-1);
return fn;
int main()
cout << fib(5) << endl;
return 0;
【讨论】:
以上是关于如何检测根递归调用?的主要内容,如果未能解决你的问题,请参考以下文章