"... есть хороший способ сделать это без использования статической переменной."
Да. Обертывание функции в классе.
В классе переменная функции static int pos может стать простым атрибутом данных оболочки.
Ниже приведены несколько примеров кода.
1) Во-первых, нужно продемонстрировать, что ваша проблема повторяется.
2) Простая оболочка класса с именем class FillAryOddFirstClass_t. Функция очень похожа на исходную, но pos не является статичной.
3) Простая оболочка Functor, называемая классом FillAryOddFirstFunctor_t. Функторы имеют более простой вызов.
4) Поскольку вы объявили этот пост как вопрос C ++, элемент 4 использует вектор вместо массива - НО обратите внимание, что код использует тот же класс для запуска рекурсии, какэлемент 2, FillAryOddFirstClass_t, который ожидает массив! Векторные данные находятся в динамической памяти, и, указав "& iVec [0] '(вместо ary), переданный адрес является начальным элементом векторных данных в куче.
5) Это элемент 2 сДоп. класс FillAryOddFirstClass2_t внутренне сложен с двумя функциями отчета. Функции отчета строят строки для отображения хода выполнения рекурсии / отклонения.
#include <iostream>
using std::cout, std::endl; // c++17
#include <iomanip>
using std::setw;
#include <string>
using std::string, std::to_string;
#include <vector>
using std::vector;
// original - with static
void fillAryOddFirst ( int ary[], int size )
{
static int pos; // <<<<<<<<<<<<<<< static
if (size <= 0) { return; }
if(size % 2 != 0) { ary[pos] = size; pos++; }
fillAryOddFirst(ary, size-1);
if(size % 2 == 0 ) { ary[pos] = size; pos++; }
return;
}
// class wrapper
class FillAryOddFirstClass_t // UDT - user defined type
{
int pos; // <<<<<<<<<<<<<<< not static, a simple attribute
public:
FillAryOddFirstClass_t() : pos (0) { }
~FillAryOddFirstClass_t() = default;
void fillAryOddFirst ( int ary[], int indx )
{
if (indx <= 0) { return; }
if(indx % 2 != 0) { ary[pos] = indx; pos++; }
fillAryOddFirst(ary, indx-1);
if(indx % 2 == 0 ) { ary[pos] = indx; pos++; }
return;
}
};
// Functor wrapper
class FillAryOddFirstFunctor_t // UDT (user defined type)
{
int pos; // <<<<<<<<<<<<<<< not static
public:
// default ctor and dtor do nothing, cost nothing
void operator()( int ary[], int indx) // functor entry
{
pos = 0; // init
fillAryOddFirst(ary, indx);
return;
}
private:
void fillAryOddFirst( int ary[], int indx)
{
if (indx <= 0) { return; }
if(indx % 2 != 0) { ary[pos] = indx; pos++; }
fillAryOddFirst(ary, indx-1);
if(indx % 2 == 0 ) { ary[pos] = indx; pos++; }
return;
}
};
// class wrapper, with cout progress indicator
class FillAryOddFirstClass2_t // UDT
{
int pos; // <<<<<<<<<<<<<<< no static
size_t sz = 10;
public:
FillAryOddFirstClass2_t() : pos (0) { }
~FillAryOddFirstClass2_t() = default;
void fillAryOddFirst ( size_t rLvl, int ary[], int indx )
{
if (indx <= 0) {
cout << "\n\n" << setw(11) << " " << "recurse end - decurse begins\n";
return;
}
if(indx % 2 != 0) { ary[pos] = indx; pos++; }
cout << rprtR (rLvl, ary); // recurse report
fillAryOddFirst (rLvl+1, ary, indx-1);
cout << rprtD (rLvl, ary); // decurse report
if(indx % 2 == 0 ) { ary[pos] = indx; pos++; }
return;
}
// report recurse
string rprtR ( size_t rLvl, int ary[])
{
std::stringstream ssOut;
ssOut << "\n " << setw(4) << rLvl
<< " " << show(ary) << ' ';
return ssOut.str();
}
// report decurse
string rprtD ( size_t rLvl, int ary[])
{
std::stringstream ssOut;
ssOut << "\n " << setw(4) << rLvl
<< " " << show(ary) << '_';
return ssOut.str();
}
string show(int ary[])
{
std::stringstream ssOut;
for (uint i=0; i<(sz-1); ++i)
if (ary[i])
ssOut << " " << ary[i];
return ssOut.str();
}
}; // class FillAryOddFirstClass2_t
Ниже приведен main (), который иллюстрирует, как каждыйиспользуется функция заполнения:
int main()
{
const size_t sz = 9;
{
cout << "\n\n Test1: original (function with static int pos) \n";
int ary[sz]; // automatic memory array
init(&ary[0], sz); // function to fill ary with 0's
show(&ary[0], sz);
// this function uses static int pos
fillAryOddFirst (&ary[0], sz);
show(&ary[0], sz);
}
{
cout << "\n\n Test2: class wrapper (no static)\n";
int ary[sz];
init(&ary[0], sz);
show(&ary[0], sz);
{
FillAryOddFirstClass_t faofObj;
faofObj.fillAryOddFirst(&ary[0], sz);
}
show(&ary[0], sz);
}
{
cout << "\n\n Test3: Functor Wrapper (no static)\n";
int ary[sz]; init(&ary[0], sz);
show(&ary[0], sz);
// no static int pos
FillAryOddFirstFunctor_t()(&ary[0], sz);
show(&ary[0], sz);
}
{
cout << "\n\n Test4: class, uses vector, not array (no static)\n";
vector<int> iVec;
for (uint i=0; i<sz; ++i) iVec.push_back(0); // vector grows
show(&iVec[0], sz);
{
FillAryOddFirstClass_t faof;
faof.fillAryOddFirst(&iVec[0], sz);
}
show(&iVec[0], sz);
}
{
cout << "\n\n Test5: class2 (no static) with graphic\n";
vector<int> iVec;
for (uint i=0; i<sz; ++i) iVec.push_back(0); // vector grows
show(&iVec[0], sz);
{
cout << "\n rlvl";
FillAryOddFirstClass2_t faof2;
faof2.fillAryOddFirst(1, &iVec[0], sz);
cout << "\n rlvl";
}
cout << "\n\n ";
show(&iVec[0], sz);
}
cout << endl;
return 0;
}
Выход:
Test1: original (function with static int pos)
0 0 0 0 0 0 0 0 0
9 7 5 3 1 2 4 6 8
Test2: class wrapper (no static)
0 0 0 0 0 0 0 0 0
9 7 5 3 1 2 4 6 8
Test3: Functor Wrapper (no static)
0 0 0 0 0 0 0 0 0
9 7 5 3 1 2 4 6 8
Test4: class, uses vector, not array (no static)
0 0 0 0 0 0 0 0 0
9 7 5 3 1 2 4 6 8
Test5: class2 (no static) with graphic
0 0 0 0 0 0 0 0 0
rlvl
1 9
2 9
3 9 7
4 9 7
5 9 7 5
6 9 7 5
7 9 7 5 3
8 9 7 5 3
9 9 7 5 3 1
recurse end - decurse begins
9 9 7 5 3 1_
8 9 7 5 3 1_
7 9 7 5 3 1 2_
6 9 7 5 3 1 2_
5 9 7 5 3 1 2 4_
4 9 7 5 3 1 2 4_
3 9 7 5 3 1 2 4 6_
2 9 7 5 3 1 2 4 6_
1 9 7 5 3 1 2 4 6 8_
rlvl
9 7 5 3 1 2 4 6 8