我无法理解这个程序是做什么的,它是一个递归的程序

时间:2016-12-07 11:24:44

标签: c arrays function recursion

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define SIZE 10 

int whatIsThis(const int b[], size_t p);

int main(void) {
    int x;
    int a[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    x = whatIsThis(a, SIZE);

    printf("result is %d\n", x);

    _sleep(1000 * 100);
}

int whatIsThis(const int b[], size_t p) {
    if (1 == p) {
        return b[0];
    } else {
        return b[p - 1] + whatIsThis(b, p - 1);
    }
}

很抱歉提出这个问题,但我几乎是C编程的初学者,我无法理解这个程序的逻辑,特别是return b[p-1]+ whatIsThis(b,p-1);。这是什么逻辑?

3 个答案:

答案 0 :(得分:6)

为了理解代码,您必须仔细阅读。发布的代码很糟糕,即使是精明的程序员也很难阅读。首先缩进并将程序与我在编辑中的方式区分开来。

函数whatIsThis()首先测试其第二个参数p是否具有值1,并且愚蠢的反转语法(1 == p)在一次蹩脚的尝试中检测到可能存在错误的== { {1}}运算符:1 = p将是语法错误,而p = 1在语法上是正确的,但不是p上的测试。

第二个参数的名称具有误导性,它是b中元素的数量。因此,将其命名为nlencount ...而不是p,这通常用于指针,将更具可读性。

如果此大小为1,则该函数返回数组的第一个元素的值。

如果没有,它返回最后一个元素的总和以及对同一个数组和少一个元素的调用结果。

因此,该函数计算数组元素的总和。

请注意,此函数是伪造的:它无法处理0的{​​{1}}值并调用未定义的行为。一个更简单,更安全的版本是:

p

或者:

int whatIsThis(const int b[], size_t n) {
    if (n == 0) {
        return 0;
    } else {
        return b[n - 1] + whatIsThis(b, n - 1);
    }
}

当然,对于这样一个简单任务的递归方法是有风险的,因为它可以非常深入地进入堆栈并为中等大小的数组调用未定义的行为。编译器不能总是优化递归,特别是当它不是尾递归时,这通常不是。

答案 1 :(得分:3)

  

这是什么?

这是一个具有未定义行为的函数。:)

当第二个参数等于0时,函数尝试访问位置p - 1中的内存,通常因为类型size_t是无符号类型而被转换为可以存储的最大值在size_t类型的对象中。

此外,由于函数内部使用了加法运算,因此可能存在两个大数的溢出。因此,函数的返回类型应该是其他更大的整数类型。

所以让我们重写一下去除这些缺点的功能。逻辑将是相同的。

long long int whatIsThis( const int a[], size_t n ) 
{
    return n == 0 ? 0 : a[n-1] + whatIsThis( a, n - 1 );
}

或者不使用三元(条件)运算符,函数看起来像

long long int whatIsThis( const int a[], size_t n ) 
{
    if ( n == 0 ) 
    {
        return 0;
    }
    else 
    {
        return a[n-1] + whatIsThis( a, n - 1 );
    }
}

现在让我们考虑一下这个功能是如何工作的。如果你有这样的数组

int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

您可以通过以下方式设想(虽然此代码不会被编译)

int a[10] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10 };

或者像这样

int a[10] = { a1[9], 10 };

其中a1 [9]是9个元素的数组

int a1[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9  };

反过来,数组a1可以想象为

int a1[9] = { a2[8], 9 };

其中a2是

int a2[8] = { 1, 2, 3, 4, 5, 6, 7, 8  };

等等,最后我们会得到

int a8[2] = { a9[1], 2 };

其中a9是

int a9[1] = { 1 };

那么这个功能是做什么的?

对于想象为

的数组a
int a[10] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10 };

或喜欢

int a[10] = { a1[9], 10 };

该函数添加了a1[9] + 10

反过来想象

的数组a1
int a1[9] = { 1, 2, 3, 4, 5, 6, 7, 8 }, 9  };

或喜欢

int a1[9] = { a2[8], 9 };

该函数计算a2[8] + 9

如果使用a1[9]替换表达式a1[9] + 10中的a2[8] + 9,我们将获得a2[8] + 9 + 10,依此类推。

因此该函数计算数组元素的总和。

答案 2 :(得分:1)

该函数以递归方式计算数组中元素的总和。

第一次调用函数时p = 10。部分 return b[p-1]+ whatIsThis(b,p-1)b[9]并使用whatIsThis(b,9)调用该函数,该函数将返回 return b[8]+ whatIsThis(b,8) ...一直到 return b[1]+ whatIsThis(b,1)将返回b[0] 1}}。