Search code examples
c++recursionimplementation

I'm trying to sum up the numbers in a given array, using recursion , tried this code but it isn't working. Why?


#include <iostream>

   using namespace std;

   int sumByRecursion( int arr[]) {
        int sum = 0;
        int n = sizeof(arr)/sizeof(arr[0]);
        //n is the size of the array
        if (n == 0) {
            return sum;
        } else {
            n -= 1;
            for (int i=0;i=n;++i){
                arr[i]=arr[i+1];
            }
            return (sum + arr[0] + sumByRecursion( arr));
        }
    }

   int main() {
        int arr[]={2, 4, 6};
        sumByRecursion( arr);

        return 0;
    }
    

sumByRecursion working based on this idea: 1-if the size of the array is 0 "empty array", return the sum. 2-if size isn't 0 "array isn't empty", sum up the first element on sum, then call the function, reduce the array's size by 1, sumByRecursion on the new array.


Solution

  • A (sadly) common mistake:

    int sumByRecursion( int arr[] )
    { // What do you think  ^^^^^  this is?
    
        int n = sizeof(arr)/sizeof(arr[0]);
        //      ^^^^^^^^^^^ Sorry, too late.
        // ...
    }
    

    As already noted in the comment section

    Inside the function the parameter arr has decayed to type int* and knows nothing about the number of elements in the array. (Richard Critten)

    In short: int sumByRecursion( int arr[]) is exactly the same as int sumByRecursion( int *arr). That [] syntax in the parameter list is nothing more than syntax sugar. (PaulMcKenzie)

    The solution is to pass the size alongside the pointer, either explicitly as a separate function argument or inside an object like std::span or std::ranges::range.

    An alternative, of course, is to pass the couple of iterators returned by std::cbegin() and std::cend().


    The code used to "reduce the array's size by 1" is probably a result of the same misunderstanding:

    int sum = 0;
    // ...
    if (n == 0) {              // Ok...
        return sum;
    } else {
        n -= 1;                // Okayish...
       
        for (int i=0;i=n;++i){ // 
            arr[i]=arr[i+1];   // <-- There's NO need to do all those copies!
        }                      // 
    
        return (sum + arr[0] + sumByRecursion( arr));
        //                                    ^^^^ This does NOT pass an array
    }
    

    Eljay's answer shows how to correctly implement OP's algorithm.

    Just for fun(1), a stack-friendlier implementation

    #include <iostream>
    
    int sumByRecursion(size_t n, int const* arr)
    {
        // Stop the bloody recursion
        if ( n == 0 )
            return 0;
        if ( n == 1 )
            return arr[0];
        
        // Divide et impera
        size_t middle = n / 2;
        return sumByRecursion(middle, arr)
             + sumByRecursion(n - middle, arr + middle);
    }
    
    int main()
    {
        int arr[] {2, 4, 6};
    
        std::cout << sumByRecursion(std::size(arr), arr) << '\n';
    }
    

    (1) Seriously, do NOT use this. It's utterly inefficient and uselessly convoluted. Use the right algorithm instead.