数组这玩意,我想很难找到不支持这种数据结构类型的语言了。
但是教材上为什么还要自己实现呢?因为相对一位数组来说,多维数组还是复杂些的吧?
一开始也是觉得简单到不想实现,后来在多维数组的显示函数上,还是费了点脑筋的,用到了递归。
此外要注意一定要作参数合法性检测,否则一不小心把a.Assign(100,0,0,0)写成a.Assign(0,0,0,100)这种,就会在调试时报错,让你莫名其妙半天。
主要要记录基址、维度、各维长度,此外记录一些辅助性的计算offset时要用的数值。
不考虑什么默认参数之类的情况了。
代码如下:
/*
2014.4.22
多维数组
*/
#include <iostream>
#include <cstdarg>
using std::cout;
using std::endl;
#define MAX_DIM 8
class CMyArray
{
private:
int *base; //基址
int dim; //维度
int bounds[MAX_DIM]; //每一维的长度
int total_memory; //总占用空间
int counts[MAX_DIM]; //行主序存储时,每一维的总空间大小(越靠前的维度,此值越大),便于计算元素位置
public:
CMyArray(int dims, ...);
~CMyArray();
void Assign(int data, ...);
void Value(int *result, ...);
void Show(int dims, int &pos);
inline int GetDims(){return dim;}
inline int GetTotalMem(){return total_memory;}
inline int *GetBase(){return base;}
};
CMyArray::CMyArray(int dims, ...)
{
if ((dims > MAX_DIM) || (dims < 0))
{
cout<<"Invalid Param"<<endl;
exit(0);
}
dim = dims;
va_list ap;
va_start(ap, dims);
//记录各维长度,并计算总占用空间大小
total_memory = 1;
for(int i=0; i<dims; ++i)
{
bounds[i] = va_arg(ap, int);
if (bounds[i]<0)
{
cout<<"Invalid Param"<<endl;
exit(0);
}
total_memory *= bounds[i];
}
va_end(ap);
base = new int[total_memory]();
//计算各维空间大小
counts[dims-1] = 1;
for(int i=dims-2; i>=0; --i)
{
counts[i] = counts[i+1]*bounds[i+1];
}
}
CMyArray::~CMyArray()
{
delete base;
base = NULL;
}
void CMyArray::Assign(int data, ...)
{
//计算偏移量
int pos = 0;
va_list ap;
va_start(ap, data);
for(int i=0; i<dim; ++i)
{
int arg = va_arg(ap, int);
if ((arg<0)||(arg>=bounds[i]))
{
cout<<"Invalid Param"<<endl;
exit(0);
}
pos += arg*counts[i];
}
va_end(ap);
//赋值
*(base + pos) = data;
}
void CMyArray::Value(int *result, ...)
{
//计算偏移量
int pos = 0;
va_list ap;
va_start(ap, result);
for(int i=0; i<dim; ++i)
{
int arg = va_arg(ap, int);
if ((arg<0)||(arg>=bounds[i]))
{
cout<<"Invalid Param"<<endl;
exit(0);
}
pos += arg*counts[i];
}
va_end(ap);
//取值
*result = *(base + pos);
}
//最低维(0维)数据间用空格隔开,其他各维间用换行加两个空格隔开
void CMyArray::Show(int dims, int &pos)
{
//最后一维将数据横排显示
if (1 == dims)
{
//排版,根据维度深度在每行开头打印相应空格
int j = dim-dims;
while (j>0)
{
cout<<" ";
j--;
}
for(int i=0; i<bounds[dim-dims]; ++i)
{
cout<<*(base+pos)<<" ";
if (pos < (total_memory - 1))
{
pos++;
}
}
}
//若不是最后一维,递归处理
else
{
for(int i=0; i<bounds[dim-dims]; ++i)
{
int j = dim-dims;
while (j>0)
{
cout<<" ";
j--;
}
//每次退出递归前,要恢复维度数
int dims_tmp = dims;
cout<<"dim "<<(dim-dims)<<":"<<i<<endl;
Show(--dims, pos);
cout<<endl;
dims = dims_tmp;
}
}
}
int main()
{
CMyArray a(3, 4, 4, 4); //3维数列,每维长度均为4
a.Assign(100, 0, 0, 0); //a[0][0][0] = 100
a.Assign(200, 1, 2, 3); //a[1][2][3] = 200
int result;
a.Value(&result, 1, 2, 3);
cout<<result<<endl; //显示a[1][2][3]
int pos = 0;
a.Show(a.GetDims(), pos); //显示多维数组全部数据
//顺序赋值并显示
for(int i=0; i<a.GetTotalMem(); ++i)
{
*(a.GetBase()+i) = i;
}
pos = 0;
a.Show(a.GetDims(), pos);
a.Assign(100, 4, 0, 0); //非法参数
}
/*
运行结果:
200
dim 0:0
dim 1:0
100 0 0 0
dim 1:1
0 0 0 0
dim 1:2
0 0 0 0
dim 1:3
0 0 0 0
dim 0:1
dim 1:0
0 0 0 0
dim 1:1
0 0 0 0
dim 1:2
0 0 0 200
dim 1:3
0 0 0 0
dim 0:2
dim 1:0
0 0 0 0
dim 1:1
0 0 0 0
dim 1:2
0 0 0 0
dim 1:3
0 0 0 0
dim 0:3
dim 1:0
0 0 0 0
dim 1:1
0 0 0 0
dim 1:2
0 0 0 0
dim 1:3
0 0 0 0
dim 0:0
dim 1:0
0 1 2 3
dim 1:1
4 5 6 7
dim 1:2
8 9 10 11
dim 1:3
12 13 14 15
dim 0:1
dim 1:0
16 17 18 19
dim 1:1
20 21 22 23
dim 1:2
24 25 26 27
dim 1:3
28 29 30 31
dim 0:2
dim 1:0
32 33 34 35
dim 1:1
36 37 38 39
dim 1:2
40 41 42 43
dim 1:3
44 45 46 47
dim 0:3
dim 1:0
48 49 50 51
dim 1:1
52 53 54 55
dim 1:2
56 57 58 59
dim 1:3
60 61 62 63
Invalid Param
注意点:
1,对各函数的输入参数一定要作合法性检测
2,递归显示各维数据时,注意下次序关系。
*/