n维数组实现(可变参数表的使用)

首先先介绍一下可变参数表需要用到的宏:

头文件:#include<cstdarg>

void va_start( va_list arg_ptr, prev_param ); 
type va_arg( va_list arg_ptr, type ); 
void va_end( va_list arg_ptr );

 

va_list:用来保存宏va_start、va_arg和va_end所需信息的一种类型。为了访问变长参数列表中的参数,必须声明
             va_list类型的一个对象       定义: typedef char *  va_list;
va_start:访问变长参数列表中的参数之前使用的宏,它初始化用va_list声明的对象,初始化结果供宏va_arg和
               va_end使用;
va_arg: 展开成一个表达式的宏,该表达式具有变长参数列表中下一个参数的值和类型。每次调用va_arg都会修改
              用va_list声明的对象,从而使该对象指向参数列表中的下一个参数;
va_end:该宏使程序能够从变长参数列表用宏va_start引用的函数中正常返回。
va在这里是variable-argument(可变参数)的意思. 
这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件.下面我们写一个简单的可变参数的函数,改函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值.

/*C++中好像不区分内部类与嵌套类两个名词。内部类与嵌套类都是指在类中定义类。局部类是指在函数中定义类。(c++不能在函数中定义函数。c++在类中定义的函数也就是成员函数。)(c++内部类与java内部类最大的区别就是:c++的内部类对象没有外部类对象的指针,不能访问外部类对象的非静态成员;java的非静态内部类对象有外部类对象的指针,能访问外部类对象的非静态成员。)
*/
#include<cstdarg>//标准头文件,提供宏va_start, va_arg, 和 va_end 
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string>
#include<cstring>
#define MAX_ARRAY_DIM 8 //假设数组的维数的最大值为8 
using namespace std;template <typename ElemType>
class MyArray{private:public:class Array{public:ElemType *base;//数组元素的基址 int dim;//数组的维数int * bounds;//数组维界基址int * constants; //数组映像函数常量基址 
        };static const int ERROR = -1;static const int OK = 1;int InitArray(Array &A, int dim, ...);//若维数dim和随后的各维的长度合法,则构造相应的数组A int DestoryArray(Array &A);//销毁数组A int Value(Array A, ElemType &e, ...);//A是n为数组,e为元素变量,随后是n个下标值,将下标值对应的元素赋给e int Assign(Array &A, ElemType e, ...);//将元素e赋给指定的下标值int Locate(Array A, va_list ap, int &off);//返回指定的下标值对应的偏移地址, 存放在off 
};template <typename ElemType>
int MyArray<ElemType>::InitArray(Array &A, int dim, ...){if(dim<1 || dim > MAX_ARRAY_DIM) return MyArray::ERROR;A.dim = dim;A.bounds = (int *)malloc(dim * sizeof(int));if(!A.bounds) return MyArray::ERROR;int elemtotal = 1;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) return MyArray::ERROR;elemtotal *= A.bounds[i];}va_end(ap);A.base = (ElemType *)malloc(elemtotal * sizeof(ElemType));if(!A.base) return MyArray::ERROR;A.constants = (int *)malloc(dim * sizeof(int));if(!A.constants) return MyArray::ERROR;//开始求映像数组//int L = sizeof(ElemType);//每一个元素的大小int L = 1;//注意这里的元素的单位大小就是 1, 因为 A.base + off 实际上是 A.base+off*sizeof(ElemType);A.constants[dim-1] = L; for(int i=dim-2; i>=0; --i)A.constants[i] = A.bounds[i+1] * A.constants[i+1];return MyArray::OK;
}template <typename ElemType>
int MyArray<ElemType>::DestoryArray(Array &A){if(!A.base) return MyArray::ERROR;free(A.base);if(!A.bounds)  return MyArray::ERROR;free(A.bounds);if(!A.constants) return MyArray::ERROR;free(A.constants);
}
template <typename ElemType>
int MyArray<ElemType>::Value(Array A, ElemType &e, ...){va_list ap;int off;va_start(ap, e);if(Locate(A, ap, off)==MyArray::ERROR) return MyArray::ERROR;e = *(A.base+off);va_end(ap);return MyArray::OK;
}template <typename ElemType>
int MyArray<ElemType>::Assign(Array &A, ElemType e, ...){va_list ap;int off;va_start(ap, e);if(Locate(A, ap, off)==MyArray::ERROR) return MyArray::ERROR;*(A.base+off) = e;va_end(ap);return MyArray::OK;
}template <typename ElemType>
int MyArray<ElemType>::Locate(Array A, va_list ap, int &off){off = 0;for(int i=0; i<A.dim; ++i){int ind = va_arg(ap, int);if(ind<0 || ind >= A.bounds[i]) return MyArray::ERROR;off += A.constants[i]*ind;}return MyArray::OK;
}class Student{public:char *name; int age;Student(){}Student(char *name, int age){this->name = name;this->age = age; }void outMsg(){cout<<"姓名: " << name << ", 年龄: " << age;}
};int main(){MyArray<int> testArray;MyArray<int>::Array A;testArray.InitArray(A, 4, 1, 2, 3, 4);for(int i=0; i<1; ++i)for(int j=0; j<2; ++j)for(int k=0; k<3; ++k)for(int n=0; n<4; ++n){int e = i+j+k+n;testArray.Assign(A, e, i, j, k, n);}for(int i=0; i<1; ++i)for(int j=0; j<2; ++j)for(int k=0; k<3; ++k)for(int n=0; n<4; ++n){int e;testArray.Value(A, e, i, j, k, n);printf("%d\n", e);}MyArray<Student> testArrayx;MyArray<Student>::Array Ax;testArrayx.InitArray(Ax, 3, 4, 10, 20);//4, 10, 20分别表示六层, 座位行号, 座位列号 Student s("hjzgg", 23);testArrayx.Assign(Ax, s, 1, 2, 3);s.name = "lxkdd"; testArrayx.Value(Ax, s, 1, 2, 3);s.outMsg();return 0;
}

 

转载于:https://www.cnblogs.com/hujunzheng/p/4639440.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531469.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

回流焊和波峰焊的区别

本文首先分别介绍回流焊和波峰焊的特点&#xff0c;然后对两者进行比较&#xff0c;欢迎评论补充哦~ 最近在实习看到了厂里面的回流焊的波峰焊&#xff0c;有点好奇就查了点资料&#xff0c;分享给同样爱学习的你。 一.回流焊 一般的表面贴装工艺分三步&#xff1a;印刷机施加…

三对角矩阵的压缩

三对角矩阵&#xff0c;从第二行开始选中的元素的个数都为3个。对于a[i,j]将要存储的位置k&#xff0c;首先前(i-1)行元素的个数是(i-2)*3 2(第一行元素的个数为2)&#xff0c;又a[i,j]属于第i行被选中元素的第j-i1个元素&#xff0c;所以k (i-2)*3 2 j-i1 2*ij-3 如果知道了…

LC和RC滤波电路分析

一、概述 整流电路的输出电压并不是纯粹的直流&#xff0c;从示波器观察整流电路的输出&#xff0c;与直流相差很大&#xff0c;波形中含有较大的脉动成分&#xff0c;称为纹波。为了获得比较理想的直流电压&#xff0c;需要利用具有储能作用的电抗性元件(如&#xff1a;电感、…

dev c++ Boost库的安装

dev c 的boost库的安装步骤 然后点击“check for updates”按钮 最后点击“Download selected”按钮&#xff0c;下载完成后安装.... 给dev添加boost库文件&#xff0c;找到之前安装的目录 #include<iostream> #include<string> #include<cstring> #include…

(一)C语言之数据类型

在这里主要讲了基本的知识&#xff0c;具体练习时注意用代码看看数据存储的位数和大小&#xff0c;像char a127;aa1;这时候a的值。可以用sizeof查看数据类型占的字节数。以及不同数据类型之间如何自动转换和强制转换&#xff0c;还有printf和scanf的具体用法&#xff0c;多动手…

十字链表的应用

#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #define MAX_VERTEX_NUM 20 using namespace std; typedef struct ArcBox{int tailVex, headVex;//该弧的尾和头顶点的位置 struct ArcBox *hlink, *tlink;//分别为弧…

(二)C语言数据类型(2)

今天主要总结了一下运算符&#xff0c;详细介绍了运算符分类和优先级的基本知识 欢迎加入嵌入式学习群&#xff1a;559601187 运算符按操作数可以分为&#xff1a;单目运算符、双目运算符和三目运算符&#xff0c;优先级依次为单目运算符>双目运算符>三目运算符,在c语言里…

AOE网的关键路径的计算

求关键路径&#xff0c;只需理解顶点&#xff08;事件&#xff09;和边&#xff08;活动&#xff09;各自的两个特征属性以及求法即可&#xff1a; 先根据首结点的Ve(j)0由前向后&#xff08;正拓扑序列&#xff09;计算各顶点的最早发生时间 再根据终结点的Vl(j)等于它的V…

(三)C语言之九条语句

今天来说一下我们以后可能用的最多的C语言语句&#xff1a;条件语句、循环语句、控制语句。理论很简单&#xff0c;注重多自己写代码才能熟练运用。 欢迎加入嵌入式学习群&#xff1a;559601187 一起愉快的玩耍啊~ &#xff08;一&#xff09;条件语句 &#xff08;1&#xff…

C语言之getchar()用法

(1)语法 int getchar(void);(2)返回值 getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用…

次优查找树的建立

查找效率最高即平均查找长度最小&#xff0c;根据前面所学知识&#xff0c;我们可以给出有序表在非等概率情况下应遵循的两个原则&#xff1a; 1、最先访问的结点应是访问概率最大的结点&#xff1b; 2、每次访问应使结点两边尚未访问的结点的被访概率之和尽可能相等。 这两…

(四)C语言之数组

讲一下数组的相关知识&#xff0c;数组在以后的编程还是很重要的&#xff0c;希望大家认真学习&#xff0c;同时也勉励自己。 欢迎加入嵌入式学习群&#xff1a;559601187 在C语言中使用数组必须先进行定义&#xff0c;数组属于构造数据类型的一种&#xff0c;它是一组相同数据…

平衡二叉树AVL插入

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的&#xff0c;所以又称为AVL树。 定义&#xff1a;平衡二叉树或为空树,或为如下性质的二叉排序树: &#xff08;1&#xff09;左右子树深度之差的绝对值不超过1; &…

C语言练习(一)

今天来讲解一下数组相关的习题&#xff0c;巩固昨天的知识 欢迎加入嵌入式学习群&#xff1a;559601187 1.对于二维数组首地址偏移。 二维数组数组名偏移一个数&#xff0c;地址偏移一行&#xff0c;针对这个问题后面会做一个详细的讲解 #include <stdio.h> int main() …

(五)C语言之二维数组

今天的第二个内容单独拿出来讲一下&#xff0c;对于初接触C语言的人来说&#xff0c;这个知识点比较难懂&#xff0c;后面在讲指针的时候我还会提到这部分的内容&#xff0c;看不懂的同学可以看后面的内容。 指针变量可以指向一维数组中的元素&#xff0c;当然也就可以指向二维…

平衡二叉树AVL删除

平衡二叉树的插入过程: http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p&#xff0c;其双亲是*f&#xff0c;不失一般性&#xff0c;设*p是*f的左孩子&#xff0c;下面分三种情况讨论&#xff1a;  ⑴…

(六)C语言之函数

本篇文章分为三个部分讲解&#xff0c;分别为函数、局部变量和全局变量、c语言存储分区 &#xff08;一&#xff09;函数的定义和调用 函数&#xff1a;工程中最小的单位&#xff0c;为了实现某一功能的 函数的定义&#xff1a; 数据类型 函数名(数据类型 形参1&#xff0c;…

堆排序算法---属于选择排序

1.堆 堆实际上是一棵完全二叉树&#xff0c;其任何一非叶节点满足性质&#xff1a; Key[i]<key[2i1]&&Key[i]<key[2i2]或者Key[i]>Key[2i1]&&key>key[2i2] 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。 堆分为大顶堆和小顶堆…

(七)C语言之指针

c语言相比其他高级语言来说&#xff0c;更接近于对计算机硬件的操作&#xff0c;而指针的应用更是为我们对硬件的操作插上了翅膀&#xff0c;所以指针是嵌入式编程不可少的一部分&#xff0c;在一定意义上说&#xff0c;指针是c语言的精髓。 一、 什么是指针 在计算机中&#…

各种排序(数据结构复习之内部排序算法总结)

1.三种选择排序&#xff08;简单选择排序&#xff0c;树形选择排序&#xff0c;堆排序&#xff09; #include<iostream> #include<cstring> #include<string> #include<queue> #include<map> #include<cstdlib> #include<cstdio> c…