天天看点

数组的顺序表示和实现:利用可变参数列表实现多维数组的创建数组的顺序表示和实现:利用可变参数列表实现多维数组的创建

数组的顺序表示和实现:利用可变参数列表实现多维数组的创建

对于可变参数列表的详细介绍,参见文章:《C语言函数的可变参数列表》。完整代码可在CSDN资源中搜索《数组的顺序存储表示和实现:利用可变参数列表实现多维数组的创建,元素赋值等操作》进行下载。

#include<stdarg.h>
#include<stdio.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0
#define MAX_ARRAY_DIM 8   //设置数组的最大维度


typedef int ElemType;
typedef struct{
	ElemType *base;		//存数数组数据项的基址
	int dim;			//存储数组的维度
	int *bounds;		//数组维界基址存数每个维度的长度
	int *constants;    //存储每个维度指针的增减的单位,即数组在该维度的下标增加一对应几个</span><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;">ElemType类型的单位。如三维整型数组的第一维空间下标增减一对应一个整型内存空间的偏移,第二维空间的下表增减1对应第一维的长度个整型内存空间的偏移,第三维空间的下表增减1对应前两维的长度相乘个整型内存空间的偏移</span></span><span style="font-size:14px;">

}Array;</span>           
void InitArray( Array *ary, int dim, ... );//根据参数构造数组ary
int Locate( Array *ary, va_list ap, int *offset );//判断给定的下标范围是否符合要求
int Assign( Array *ary, ElemType e, ... );//将数组的某个单元赋值为e
int Value( Array *ary, ElemType *e, ... );
void Destroy( Array *ary );

//若维数和随后的各维长度合法,则构造相应的数组
//注意此函数不能对数组元素进行初始化
void InitArray( Array *ary, int dim, ... )
{
	va_list var_arg;    //可变参数列表
	int i;
	int elemtotal = 1;   //用于统计数组元素的总个数

	if( dim < 1 || dim > MAX_ARRAY_DIM ){	  //如果维度小于1或大于限定的最大维度,则返回错误并结束程序执行	
		printf( "InitArray Error: WRONG DIM!\n" );
		exit( EXIT_FAILURE );
	}
	va_start( var_arg, dim );    //可变参数的第一个参数
	ary->dim = dim;             //将数组维度置为参数中给出的维度
	ary->bounds = ( int *)malloc( dim *sizeof( int ) );   //为存数每个维度的长度的数组分配空间
	if( ary->bounds ){   //分配成功则将dim后的参数按顺序赋给相应的内存单元
		for( i = 0; i < dim; i++ ){
			*( ary->bounds + i ) = va_arg( var_arg, int );
			if( *( ary->bounds + i ) <= 0 ){
				printf( "InitArray Error: WRONG ARRAY BOUNDS!\n" );
				exit( EXIT_FAILURE );
			}
			elemtotal *= *( ary->bounds + i );   //数组的总元素的个数等于各个维度长度的乘积
		}
		va_end( var_arg );
	}
	else{
			printf( "InitArray Error: OVERFLOW!\n" );
			exit( EXIT_FAILURE );
	}
	ary->base = ( ElemType * )malloc( sizeof( ElemType ) * elemtotal );   //为存放数组元素的数据块分配内存单元
	if( !ary->base ){
		printf( "InitArray Error: OVERFLOW!\n" );
		exit( EXIT_FAILURE );
	}

	ary->constants = ( int * )malloc( sizeof( int ) * dim );   //为存放指针增减单位的数据块分配内存单元
	if( !ary->constants ){
		printf( "InitArray Error: OVERFLOW!\n" );
		exit( EXIT_FAILURE );
	}
	*( ary->constants + dim - 1 ) = 1;   //最后一个维度的指针的增减以元素的大小为单位
	for( i = dim -2; i >= 0; i-- ){
		*( ary->constants + i ) = *( ary->bounds + i + 1 ) * *( ary->constants + i + 1 );
		//前一个维度指针增减一对应的单位是后一个维度的单位乘以后一个维度的长度
	}	
}           
//判断给出的下标值是否合法,若合法,则计算出对应基址的偏移
int Locate( Array *ary, va_list ap, int *offset ) //第二个参数类型为va_list,即为数组元素的下标组合,根据该可变参数列表的所有值来求得offset
{
	int i;
	int ind;           //每个维度对应的下标值

	*offset = 0;

	for( i = 0; i < ary->dim; i++ ){
		ind = va_arg( ap, int );
		if( ind < 0 || ind >= *( ary->bounds + i ) )
			return FALSE;
		else{
			*offset += ind * (*( ary->constants + i ));
		}
	}
	return TRUE;
}

//将数组给定下标的元素赋值为e
int Assign( Array *ary, ElemType e, ... )  //省略号后的参数就是需要被赋值的数组元素对应的下标
{
	va_list var_arg;
	int offset;

	va_start( var_arg, e );
	if( Locate( ary, var_arg, &offset ) ){
		*( ary->base + offset ) = e;
		return TRUE;
	}	
	else
		return FALSE;
}


//将数组给定下标的元素的值赋给e,与Assign的赋值方向是相反的
int Value( Array *ary, ElemType *e, ... ) //省略号后的参数就是需要赋值给e的数组元素对应的下标
{
	va_list var_arg;
	int offset;

	va_start( var_arg, e );
	if( Locate( ary, var_arg, &offset ) ){
		*e = *( ary->base + offset );
		return TRUE;
	}	
	else
		return FALSE;
}

void Destroy( Array *ary )
{
	if( !ary->base || !ary->bounds || !ary->bounds )
	printf( "Destroy Error!\n" );
	else{
		free( ary->base );
		free( ary->bounds );
		free( ary->constants );
	}
}           

继续阅读