预备知识
库函数<stdarg.h>
C语言该头文件定义了变量类型va_list和三个宏,分别是va_start()、va_arg()、va_end(); 主要功能是在函数参数未知的情况下获取函数参数;即下面类型的函数;
//参数固定的函数
void add(int total,num1,num2,num3)
//参数未知的函数,格式以 ...结束
void add(int total,...)
- va_list用来定义变量对象
- va_start(参数1,参数2):初始化变量,参数1为变量对象,参数2为传入函数的最后 一个固定参数,即省略号前面的第一个,上面代码就是total
- va_arg():获取参数
- va_end():函数返回
应用:
#include<stdarg.h>
int Sum(int num, ...)
{
int i, val = 0;
va_list ap;
va_start(ap, num);
for(i = 0; i < num; i++)
{
val += va_arg(ap, int);
}
va_end(ap);
return val;
}
int main()
{
printf("10, 20, 30的和为 %d\n", Sum(3, 10, 20, 30));
printf("4, 5, 6, 7的和为 %d\n", Sum(4, 4, 5, 6, 7));
return 0;
}
/* 运行结果
10, 20, 30的和为 60
4, 5, 6, 7的和为 22
Program ended with exit code: 0
*/
数组和线性表
存储的元素都必须属于同一数据类型,数组实质是存储结构,用一组连续的存储单元存放数据,而线性表则是数据结构中的一种逻辑结构,线性表需要借助数组来实现顺序存储结构;一维数组就相当于定长的线性表,二维数组可以看作每个元素都是定长线性表的定长线性表,多维数组可以看作线性表的推广;
几乎所有的程序设计语言中都将数组作为固有类型,通过数组不仅可以实现线性表的顺序存储结构,同样也可以用来构造栈、队列、串的顺序存储结构;
多维数组
int a[10][10] //定义一个整型的二维数组
二维数组可以看作每个数据元素存放的都是一个一维数组,三维数组可以看作每个元素都是一个二维数组的一维数组;同理,四维等也是如此;
多维数组的顺序存储表示
顺序存储中是先开辟一个元素基址base,根据元素的下标值,找到其元素地址,然后进行存取操作,
获取元素地址(以二维数组为例 )
int a[3][3]
//假设a中元素为1、2、3、4、5、6、7、8、9
//图形表示
1 2 3
4 5 6
7 8 9
/*
上面二维数组的存储结构实际上是
base[0]==1,base[1]==2、...、base[8]==9
然而以二维数组表示则是
a[0][0]==1,a[0][1]==2,a[0][2]==3
a[1][0]==4,a[1][1]==5,a[1][3]==6
....
因此假如我们要在a[1][1]存入4,则要找到其对应的base[x]的x值;
从上面的图形我们可以看出x=1*3+0*1=3;
上面求元素基址的方法推广到一般规律,加入我们要求四维数组s[a][b][c][d]中s[2][2][1][4]的base[x]中x的值,x=2*b+2*c+1*d+4*1;
代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
#define MAX_ARRAY_DIM 8 //最大维度数
typedef struct
{
int *base; //元素基址
int dim; //维数
int *bounds; //维界基址,存放各维元素数
int *constants;//映像函数常数
}Array;
//初始化
void InitArray(Array *A,int dim,...)
{
int elemtotal=1;
if(dim<1||dim>MAX_ARRAY_DIM)
printf("维数不合法!");
A->dim=dim;
A->bounds=(int *)malloc(dim*sizeof(int));
if(!A->bounds)
exit(0);
va_list ap;
va_start(ap, dim);
for(int i=0;i<dim;i++)
{
A->bounds[i]=va_arg(ap, int);
if(A->bounds[i]<0)
exit(0);
elemtotal*=A->bounds[i];
}
va_end(ap);
A->base=(int *)malloc(sizeof(int));
if(!A->base)
exit(0);
A->constants=(int *)malloc(dim*sizeof(int));
if(!A->constants)
exit(0);
A->constants[dim-1]=1;
for(int i=dim-2;i>=0;i--)
{
A->constants[i]=A->bounds[i+1]*A->constants[i+1];
}
}
//销毁数组
int DestroyArray(Array *A)
{
if(!A->base)
return 0;
free(A->base); A->base=NULL;
if(!A->bounds)
return 0;
free(A->bounds);A->bounds=NULL;
if(!A->constants)
return 0;
free(A->constants);A->constants=NULL;
return 1;
}
//求基址
int Locate(Array A,va_list ap)
{
int off=0,ind;
for(int i=0;i<A.dim;i++)
{
ind=va_arg(ap, int);
if(ind<0||ind>=A.bounds[i])
exit(0);
off+=A.constants[i]*ind;
}
return off;
}
//给出下表求其值
int Value(Array A,...)
{
int num;
int result;
va_list ap;
va_start(ap, A);
result=Locate(A, ap);
num=A.base[result];
return num;
}
//给出下标为其赋值
void Assign(Array *A,int e,...)
{
va_list ap;
va_start(ap, e);
int result;
result=Locate(*A, ap);
*(A->base+result)=e;
}
int main()
{
Array A,*p;
p=&A;
int num;
InitArray(p, 3,2,3,4);
Assign(p, 0,1,2,3);//a[1][2][3]赋值为0
num=Value(A, 1,2,3);
printf("%d\n",num);
return 0;
}
//运行结果 0