Home > Software engineering >  I'm trying to sum up the numbers in a given array, using recursion , tried this code but it isn
I'm trying to sum up the numbers in a given array, using recursion , tried this code but it isn

Time:12-16

#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.

CodePudding user response:

You need to pass in the size of the array to the sumByRecursion routine.

The reason you need to pass the size of the array is because the array does not track its own size.

Alternatives like std::array and std::vector provide the capability of querying them for their size, but C-style arrays do not carry along that information.

The std::size function queries the type (which is a C-style array in that context) to figure out the size. Once passed as an int arr[] parameter, that arr type is int* which no longer can produce the size information.

The int arr[] parameter is a way of writing int* arr, but suggests to the reader that the arr parameter is a C-style array. Could be considered self-documenting code, when done correctly -- but many programs would express the parameter as int* arr so, alas, it is not a widespread idiom.

#include <cstddef>
#include <iterator>
#include <iostream>

using std::cout;
using std::size;
using std::size_t;

namespace {

int sumByRecursion(int arr[], size_t n) {
    if (n == 0) {
        return 0;
    } else {
        // Many C   compilers do not perform tail recursion optimization.
        // But for those that do, this will thwart tail recursion optimization.
        return arr[0]   sumByRecursion(arr 1, n-1);
    }
}

} // anon

int main() {
    int arr[] = {2, 4, 6};
    auto arr_size = size(arr);
    auto sum = sumByRecursion(arr, arr_size);
    cout << sum << "\n";
}

CodePudding user response:

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.

  • Related