ADT Array
核心知识点:
多参数函数的使用
使用标准库<cstdarg>中重要的宏定义实现函数的参数可变
Status fun(Type ele, Type e, . . .)
{
va_list(ap);//首先声明va_list类型的变量
va_start(ap,e);//然后调用va_start传入两个参数,第一个是事先定义的va_list变量,第二个是函数参数里的一个形参变量、注意:第二个参数不能是引用类型
va_arg(ap, Type);//两个参数,返回Type类型的形参列表里e的下一个参数
va_end(ap); //结束时由va_list调用,形参不一定读完
}
存在不足:两个不确定的类型转换会出现不确定的情况等
参考:https://baike.baidu.com/item/stdarg/10282385?fr=aladdin
1 #include <iostream>
2 #include <cstdio>
3 #include <cstdarg>
4
5 using namespace std;
6
7 #define MAX_ARRAY_DIM 8//数组的最大维数为8
8
9 template<class T>
10 struct array_struct{
11 T *base;
12 int dim;//维数
13 int *bounds;//数组维界基址
14 int *constants;//用于计算偏移量
15 };
16
17 template<class T>
18 class Array
19 {
20 public:
21 Array(){}
22 Array(int dim, ...);
23 ~Array() { }
24 //void InitArrary(int dim, ...);
25 void DestoryArray();
26 void Locate(va_list ap, int &off);//off为偏移量,省略的参数是元素的 定位
27 void ValueOf(T &e,int temp, ...);//将某单元值赋给e,调用函数Locate
28 void Assign(T e, ...);//将e赋值给某单元,调用函数Locate
29 void Show();//打印
30 private:
31 array_struct<T> A;
32 };
33
34 int main() {
35 Array<int> Ab(3, 2, 2, 3);//2*2*3数组
36 Ab.Assign(3, 0, 0, 0);
37 Ab.Assign(7, 0, 0, 1);
38 Ab.Assign(8, 0, 0, 2);
39 Ab.Assign(1, 0, 1, 0);
40 Ab.Assign(10, 0, 1, 1);
41 Ab.Assign(-1, 0, 1, 2);
42
43 Ab.Assign(3, 1, 0, 0);
44 Ab.Assign(7, 1, 0, 1);
45 Ab.Assign(8, 1, 0, 2);
46 Ab.Assign(1, 1, 1, 0);
47 Ab.Assign(10, 1, 1, 1);
48 Ab.Assign(-1, 1, 1, 2);
49 Ab.Show();
50
51 //验证valueof
52 int e = 0;
53 Ab.ValueOf(e,99,0, 1, 2);//99为temp,va_start()参数不能包含引用类型
54 cout << "ValueOf(0,1,2)=" << e << endl;
55
56 //验证assign
57 Ab.Assign(0, 0, 0, 0);
58 Ab.Show();
59
60 Ab.DestoryArray();
61 system("pause");
62 }
63 template<class T>
64 void Array<T>::Show()
65 {
66 int elemtotal = 1;
67 for (int i = 0, j = A.dim; i < j; i++)
68 elemtotal *= A.bounds[i];
69 cout << "数组的元素(按一维写出):" << endl << endl;
70 for (int i = 0; i < elemtotal; i++)//下标差1,0-(total-1)
71 {
72 cout << *(A.base + i) << '\t';
73 if (!((i + 1) % A.constants[0]))
74 cout << endl << endl;
75 }
76 }
77
78 template<class T>
79 void Array<T>::Assign(T e, ...) {
80 va_list(ap);
81 va_start(ap, e);
82 int off = -1;
83 Locate(ap, off);
84 *(A.base + off) = e;
85 return;
86 }
87 template<class T>
88 void Array<T>::ValueOf(T &e, int temp, ...) {
89 va_list(ap);
90 va_start(ap, temp);
91 int off = 2;
92 Locate(ap, off);//若ap错误,则程序return,暂时不做异常处理
93 e = *(A.base + off);
94 return;
95 }
96 template<class T>
97 void Array<T>::Locate(va_list ap, int &off) {
98 off = 0;
99 for (int i = 0; i < A.dim; i++)
100 {
101 int ind = va_arg(ap, T);
102 if (ind < 0 || ind >= A.bounds[i])
103 {
104 cout << "位置错误" << endl;
105 return;
106 }
107 off += A.constants[i] * ind;
108 }
109 }
110 template<class T>
111 Array<T>::Array(int dim, ...)
112 {
113 if (dim<1 || dim>MAX_ARRAY_DIM)
114 {
115 cout << "维数非法" << endl;
116 return;
117 }
118 //bounds数组用于记录dim个维度个长度
119 A.dim = dim;
120 try {
121 A.bounds = new int[dim];//开辟dim大小的int数组
122 }
123 catch (const bad_alloc &) {
124 cout << "空间开辟失败" << endl;
125 return;
126 }
127
128 //统计总共需要的T变量的空间的个数
129 int elemtotal = 1;
130 va_list(ap);
131 va_start(ap, dim);
132 for (int i = 0; i < dim; i++) {
133 A.bounds[i] = va_arg(ap, int);
134 if (A.bounds[i] <= 0) {
135 cout << "维数错误,initarray(dim,...error...)" << endl;
136 return;
137 }
138 elemtotal *= A.bounds[i];
139 }
140 va_end(ap);
141 try {
142 A.base = new T[elemtotal];//线性开辟总空间
143 }
144 catch (const bad_alloc &) {
145 cout << "总空间开辟失败" << endl;
146 return;
147 }
148 //初始化为0
149 for (int i = 0; i < elemtotal; i++)
150 *(A.base + i) = 0;
151
152 try {
153 A.constants = new int[dim];//记录偏移量的int数组constants分配空间
154 }
155 catch (const bad_alloc &) {
156 cout << "偏移量空间开辟失败" << endl;
157 return;
158 }
159
160 //计算并得到 偏移量数组constants
161 A.constants[dim - 1] = 1;
162 for (int i = dim - 2; i >= 0; i--) {
163 A.constants[i] = A.constants[i + 1] * A.bounds[i + 1];
164 }
165 return;
166 }
167
168 template<class T>
169 void Array<T>::DestoryArray() {
170 delete[]A.base;
171 delete[]A.bounds;
172 delete[]A.constants;
173 return;
174 }