#include<stdio.h>
#include<stdarg.h> //标准头文件获取变长参数表,提供宏va_start,va_arg,va_end
#include<stdlib.h>
#define MAX_ARRAY_DIM 8 //定义数组的最大维度
#define ERROR 0
#define OK 1
#define OVERFLOW -1
typedef int ElemType;
typedef int Status;
typedef struct{
ElemType * base; //数组元素的基址,由InitArray分配
int dim; //维度
int *bounds; //数组的维界基址,由InitArray分配,指向一个数组B(存储数组A的各维度的元素的数目)
int *constants; //数组映像函数常量基址,由InitArray分配,指向一个数组C, 它存放了"数组A各个维度上的数字加一时, 元素在线性结构L上所移动的距离
}Array;
//初始化数组
Status InitArray(Array *A, int dim, ...)
{
//统计元素总数目,进而分配数组的基址
int elemtotal = 1;
int i;
//判断维度是否合法
if(dim < 1 || dim > MAX_ARRAY_DIM)
{
return ERROR;
}
A->dim = dim;
//分配维界基址
A->bounds = (int *)malloc(dim * sizeof(int));
if(!A->bounds)
{
exit(OVERFLOW);
}
va_list ap;
va_start(ap, dim);
for(i = 0; i < dim; ++i)
{
A->bounds[i] = va_arg(ap, int);
if(A->bounds[i] < 0)
{
return ERROR;
}
elemtotal *= A->bounds[i]; //统计元素数目
}
va_end(ap);
A->base = (ElemType *)malloc(elemtotal*sizeof(ElemType)); //分配数组的基地址
if(!A->base)
{
exit(-1);
}
//求映像函数的常数ci,即保存指针增减移动的元素的个数
A->constants = (int *)malloc(dim * sizeof(int));
if(!A->constants)
{
exit(-1);
}
A->constants[dim-1] = 1; //最高维,指针每次移动一个元素单位
for(i = dim - 2; i >= 0; --i)
{
//第i维的指针每次移动的距离 = i+1维元素的数目 * i+1维指针每次移动的距离
A->constants[i] = A->bounds[i+1] * A->constants[i+1];
}
return OK;
}
//销毁数组
Status DestroyArray(Array *A)
{
//判断数组的基址是否为空,free(NULL)是不允许的
if(!A->base)
{
return ERROR;
}
free(A->base);
A->base = NULL;
if(!A->bounds)
{
return ERROR;
}
free(A->bounds);
A->bounds = NULL;
if(!A->constants)
{
return ERROR;
}
free(A->constants);
A->constants = NULL;
return OK;
}
//取指定的位置的元素的相对地址,方便后续取值与赋值
Status Locate(Array A, va_list ap, int *off)
{
int i;
int tag;
//若各维度合法,求出该元素的相对地址
(*off) = 0; //相对于第一个元素的地址
for(i = 0; i < A.dim; ++i)
{
tag = va_arg(ap, int);
if(tag < 0 || tag > A.bounds[i])
{
return ERROR; //维度不合法
}
(*off) = (*off) + tag * A.constants[i]; //注意是tag,不明白画图三维数组
}
return OK;
}
//取指定下标元素的值,赋值给e
Status Value(Array A, ElemType *e, ...)
{
int result, off;
va_list ap;
va_start(ap, *e);
if((result = Locate(A, ap, &off)) <= 0)
{
return result;
}
(*e) = *(A.base + off);
return OK;
}
Status Assign(Array *A, ElemType e, ...)
{
va_list ap;
va_start(ap, e);
int result, off;
if((result = Locate(*A, ap, &off)) <= 0)
{
return result;
}
*(A->base + off) = e;
return OK;
}
int main(void)
{
Array A;
int e;
InitArray(&A, 3, 3, 3, 3);
Assign(&A, 10, 0, 1, 2);
Value(A, &e, 0, 1, 2);
printf("%d", e);
return 0;
}