递归函数中的堆栈溢出(语言C)

时间:2014-11-29 19:56:39

标签: c function visual-c++ recursion stack-overflow

我有一个任务,我应该为函数编写代码来计算几何级数(序列)的n元素。老师想要只有一个"返回"到底。



int geoprogress (int a, int q, int n)
	{
		int result;
		if (n == 0)
		{
			result = a;
		}
		if (q == 0)
		{
			return;
		}
		if (n == -1)
		{
			result = geoprogress (a, q, n + 1)/q;
		}
		else 
		{
			result = geoprogress (a, q, n - 1)*q;
		}
		return result;
	}


int _tmain(int argc, _TCHAR* argv[])
{
 	int x = 5,
		h = 3,
		p = 1,
		rez;
	const int size = 4;

	for (int i = 0; i < size; i++)
	{
	rez = geoprogress (x, h, i);
	}

	return 0;
}
&#13;
&#13;
&#13;

但是当我编写这样的代码时,我得到了#34; Stack overflow&#34;。 有谁能够帮我?如何使用函数&#34;返回&#34;来生成几何级数的n元素的函数。一旦在函数体的末尾?

1 个答案:

答案 0 :(得分:0)

你必须防止被零除。具体而言,任何时候q的值可以为零。每次输入功能时,您至少需要测试q。使用您发布的其他代码,如果您在致电q之前确保0不是geoprogress,那么这也足够了。无论如何,geoprogress中的测试是一个坚实的故障安全:

int geoprogress (int a, int q, int n)
{
    int result;
    if (n==0)
    {
        result = a;
    }
    if (q == 0)
    {
        return (value of choice);   /* or just return */
    }
    if (n == -1)
    {
        result = geoprogress (a, q, n + 1)/q;
    }
    else
    {
        result = geoprogress (a, q, n - 1)/q;
    }
    return result;
}

您还需要确保您的功能最终以n = 0或其他方式终止。这使得if (n == -1)看起来很可疑。如果n = -2怎么办? n的值逐渐变得更负,函数可能永远不会终止。在没有看到代码的其余部分的情况下,很难说,但看起来if (n == -1)会更好地用作if (n < 0)

关于何时/如何终止,函数中也存在逻辑错误。如果n > 0,您的函数会进入无限循环,在n0之间切换-1的值:

result: 0  geoprogress (2, 3, 4)
result: 0  geoprogress (2, 3, 3)
result: 0  geoprogress (2, 3, 2)
result: 0  geoprogress (2, 3, 1)
result: 0  geoprogress (2, 3, 0)  /* non-terminating loop entered */
result: 0  geoprogress (2, 3, -1)
result: 0  geoprogress (2, 3, 0)
result: 0  geoprogress (2, 3, -1)
result: 0  geoprogress (2, 3, 0)
result: 0  geoprogress (2, 3, -1)
(snip)

您的测试if (n == 0)只设置result = a并且无法控制函数返回。然后,您下次调用result = a时会立即覆盖result = geoprogress()的新值。它看起来像你打算:

if (n==0)
{
    return a;
}

否则,您的递归永远不会终止,因为n总是在0-1之间反弹,两者都不会终止递归。 为什么?想一想,看下面的代码:

if (n == -1)
{
    result = geoprogress (a, q, n + 1)/q;
}
else
{
    result = geoprogress (a, q, n - 1)/q;
}

选择n的任何值。现在问问自己什么时候会回来?答案:事实并非如此。您可以使用geoprogress再次致电n + 1,或使用geoprogress再次致电n - 1。您的功能永远不会达到return result。这就是让我相信逻辑可能是if (n == 0) return a;的原因。这为函数提供了返回的方法。这个或其中一个result =需要是return

递归函数至少需要两件事(1)在输入递归之前适当设置值,(2)是一种返回或终止的方法,递归。在递归逻辑中几乎没有设置。您唯一要做的就是测试n并按n增加或减少1。由于这是唯一的设置,因此当前编写的函数无法使递归终止。

此外,您正在执行integer division。这使得result = 0随时geoprogress (...) < q。如果您对小数值感兴趣,则需要将结果设为floatdouble以及geoprogress的类型。根据您提供的值,如果您使用3终止,则答案始终为return a;

i: 0  result: 3
i: 1  result: 3
i: 2  result: 3
i: 3  result: 3

你在建模什么,价值应该是什么?我可以继续在摘要中查看该函数,但如果我知道你在建模什么,那真的会有所帮助。这是某个方程式的代表还是一些数值扩展?当你有一个清晰的模型时递归是很棘手的,递归地对未知模型进行建模要困难得多。


在再次完成代码逻辑之后,缺少的是else子句。递归正常工作如下(让您阻止q=0,并使用整数div问题)

int geoprogress (int a, int q, int n)
{
    int result = 0;

    if (n==0)
    {
        result = a;
    }
    else
    {
        if (n == -1)
        {
            result = geoprogress (a, q, n + 1)/q;
        }
        else
        {
            result = geoprogress (a, q, n - 1)/q;
        }
    }

    return result;
}

这是您的原始代码,附加else,这是在[{1}}上终止递归所需的全部内容。如果您还有其他问题,请与我们联系。