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