递归函数返回难以理解的答案

时间:2013-09-24 02:39:02

标签: c arrays function pointers recursion

我正在为我的Computing I类编写一个小程序,其中程序接收用户决定的多个整数并计算点积。我能够使用迭代方法成功地完成它,但现在我们还必须使用递归来完成它。我计算点积的函数返回了大量不正确的数字。有时它会返回数组中最后两个值的乘积的两倍的值,当有4个其他集合没有被添加时。其他时候,我将有2个3个小数组的数组,并且返回的值是80万。这是递归函数:

//A and B are the arrays that will be dotted together, and n is number of
//elements in each array
int dotP( int *A, int *B, int n ) {
   if( n==1 ) return A[0] * B[0] ;
   return A[n-1] * B[n-1] + dotP( &A[n-1], &B[n-1], n-1);
}

3 个答案:

答案 0 :(得分:3)

究竟发生了什么

A[n-1]*B[n-1] + A[n-1 + n-2]*B[n-1 + n-2]+....

这是因为第二次递归调用,你传递的是n-1元素的地址。当它在第二次调用中计算A[n-2]时,它从n-2元素开始有效地指向n-1 nd元素,该元素是来自数组的第一个元素的2*n-3

n之后的数组中的值是垃圾(假设您已分配n个元素,或者您可能已分配超过n但未初始化它们。因此,你得到了随机的答案。 您不需要将当前数组元素的地址传递给每个递归调用。您只需传递第一个元素的地址,即A&A[0]。那你的代码工作正常。这是怎么做的:

int dotP( int *A, int *B, int n ) {
if( n==1 ) return A[0] * B[0] ;
return A[n-1] * B[n-1] + dotP( A, B, n-1) ;
}

由于AB已经是指针,因此您只需直接传递它们。希望这会有所帮助。

答案 1 :(得分:2)

... + dotP( &A[n-1], &B[n-1], n-1 );

... + dotP( &A[0], &B[0], n-1 );

因为看起来你想要处理数组的最后一项,然后将第一个(n-1)个元素传递给递归调用。记住数组总是被作为指向它们的第一个元素的指针来处理,除非你做的比这更棘手。

问题已经解决了,但是出于教育目的,尝试这个替代方案:你可以处理第一个元素并传递剩下的“尾巴”,这对LISP粉丝来说可能更令人满意:

return A[0] * B[0] + dotP( &A[1], &B[1], n-1 );

除此之外,您可以传递A + 1而不是& A [1]。

答案 2 :(得分:0)

为什么不能更好地使用:

int dotP( int *A, int *B, int n ) 
{
   if (n) return A[0] * B[0] + dotP(A + 1, B + 1, n-1);
   else return 0;
}

或以更紧凑的形式:

int dotP(int *A, int *B, int n)
{
    if (n) return A[0] * B[0] + dotP(++A, ++B, --n);
    else return 0;
}