“...有没有不使用静态变量的好方法。”
是的。将函数包装在一个类中。
在一个类中,“static int pos”函数变量可以成为包装器的简单数据属性。
以下是几个代码示例。
1) 首先是证明您的问题是可重复的。
2) 一个简单的类包装器,称为类 FillAryOddFirstClass_t。该功能与您原来的功能非常相似,但 pos 不是静态的。
3) 一个简单的 Functor 包装器,称为类 FillAryOddFirstFunctor_t。函子有一个更简单的调用。
4) 因为您已将这篇文章声明为 C++ 问题,所以第 4 项使用向量而不是数组——但请注意,代码使用与第 2 项相同的类来运行递归,FillAryOddFirstClass_t,它需要一个数组!向量数据驻留在动态内存中,通过指定“&iVec[0]”(而不是ary),传递的地址是堆中向量数据的开始元素。
5) 这是带有附加功能的第 2 项。类 FillAryOddFirstClass2_t 内部复杂,有 2 个报告函数。报告函数构建字符串以显示递归/递归执行的进度。
#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(),它说明了每个'fill'函数是如何使用的:
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