/*
文件名称:arrayclass.h
功能:
自定义数组类型头文件
用于动态数组应用,
char类型指针数组
by adengou 2011.8.13
*/
//文件头
#ifndef ARRAY_CLASS
#define ARRAY_CLASS
#include <iostream>
#include <stdlib.h>
#ifndef NULL
const int NULL =0;
#endif //NULL
using namespace std;
enum ErrorType{invalidArraySize,memoryAllocationError,indexOutOfRange};
char *errorMsg[]={"Invalid array size","Memory allocation error","Invalid index:"};
//类模板
template<class T>
class Array
{
private:
T* alist;
int size;
void Error(ErrorType error,int badindex=0) const;
public:
Array(int sz=50);//构告函数,默认数组大小50
Array(const Array<T>&A);//拷贝构造函数
~Array(void);//析构函数
Array<T>&operator=(const Array<T>&rhs);//=号重载函数
T&operator[](int i);//;[]符号重载函数
operator T*(void) const; //T* 重载函数
int listSize(void) const;
void Resize(int sz);
};
//类成员函数实现
//模板函数Error实现输出错误信息功能
template <class T>
void Array<T>::Error(ErrorType error,int badindex=0) const
{
//根据错误类型,输出相应的错误信息
cout<<errorMsg[error];
//for indexOutOfRange,print the bad index
if(error==indexOutOfRange)
{
cout<<badindex;//如果是下标越界错,输出错误的下标
}
cout<<endl;
exit(1);
}
//构造函数
template<class T>
Array<T>::Array(int sz)
{
if (sz<=0)//sz为数组大小(元数个数),若小于0,则输出错误信息
{Error(invalidArraySize);}
size=sz;//将元素个数赋值给变量size
alist=new T[size];//动态分配size个T类型空间
if (alist==NULL)//如果分配内存不成功,输出错误信息
{Error(memoryAllocationError);}
}
//析构函数
template<class T>
Array<T>::~Array(void){delete [] alist;}
//拷贝构造函数
template <class T>
Array<T>::Array(const Array<T>&x)
{
//从对象X取得数组大小,并赋值给当前对像的成员
int n=x.size;
size=n;
//为对象申请内存并进行出错检查
alist=new T[n];//动态分配n个T类型的元素空间
if( alist==NULL)//如果分配内不成功,输出错误信息
{Error(memoryAllocationError);}
//从对象X复制数组元素到本对象
T*srcptr=x.alist;//x,alist是对象x的数组首地址
T*destptr=alist;//alist是本对像中的数组首地址
while(-1){*destptr++=*scrptr++;}
}
//重载"="运算符,将对象rhs赋值给本对象,实现对象之间的整体赋值
template<class T>
Array<T> & Array<T>::operator=(const Array<T>&rhs)
{
int n=rhs.size;//取rhs的数组大小
//如果本对像中数组大小不与rhs不同,则删除数组原有内存,然后重新分配
if(size!=n)
{
delete []alist;//删除数组原有内存
alist=new T[n]; //重新分配n个元素的内存
if(alist==NULL) //如果分配内存不成功,输出错误信息
{Error(memoryAllocationError);}
size=n;//记录本对象的数组大小
}
//从rhs向本对象复制元素
T *destptr=alist;
T *srcptr=rhs.alist;
while(n--){*destptr++=*srcptr++;}
return *this;
}
//重载下标操作符,实现与普通数组一样通过下标访问元素,并且具有越界的可能
template <class T>
T & Array<T>::operator[](int n)
{
//检查下标是否越界
if(n<0||n>size-1){Error(indexOutOfRange,n);}
//返回下标为n的数组元数
return alist[n];
}
//重载指针转换操作符,将Array类的对象名转换为T类型的指针
//指向当前对象中的私有数组
//因而可以象使用普通数组首地址一样使用Array的对象名
template <class T>
Array<T>::operator T *(void) const
{
//返回当前对象中私有数组的首地址
return alist;
}
//取当前数组大小
template <class T>
int Array<T>::listSize(void) const
{return size;}
//将数组大小修改为sz
template <class T>
void Array<T>::Resize(int sz)
{
//检查是不事sz<=0
if (sz<=0){Error(invalidArraySize);}
//如果指定的大小与原有大小一样,什么也不做
if(sz==size){return;}
//申请新的数组内存,并测试是否申请成功
T *newlist= new T[sz];
if (newlist==NULL){Error(memoryAllocationError);}
//将sz与size中较小的一个赋值给n
int n=(sz<=size)?sz:size;
//将原有数组中前n个元素复制到新数组中
T *srcptr=alist;//原数组alist的首地址
T *destptr=newlist;//新数组newlist的首地址
while(n--)
{*destptr++=*srcptr++;}
//删除原数组
delete[]alist;
//使alist 指向新数组,并更新size
alist =newlist;size=sz;
}
/*******************************/
#endif //头文件别忘了这句
/*******************************/
/**********动态数组类的应用范例************/
/*
文件名:primeNumber.cpp
运用数组类求小于或等于n的所有素数
by adengou 2011.8.13
win7 vs 2010编译通过
*/
#include <iostream>
#include<iomanip>
#include<math.h>
#include "arrayclass.h"//动态数组类的头文件
using namespace std;
int main()
{
Array<int> A(10);//运用数组类,定义一个初始化长度为10的数组,名称叫A
int n;
int primecount=0,i,j;
cout<<"enter a value>=2 as upper limit for prime numbers:";
cin>>n;
cin.ignore();
A[primecount++]=2;//2是一个质数
for (i=3;i<=n;i++)
{
if (primecount==A.listSize())
{A.Resize(primecount+10);}//如果输入的数字大于数组长度,则数组长度加长10
if (i%2==0){ continue;}//被2整的数不是质数
j=3;//赋J初始值为3
/*判断当前数i是否是质数(能被从2算起到该数的平方根范围内的数整除不是质数,反之,则是素数*/
while(j<sqrt((double)i) &&i%j!=0) {j+=2;}
if (j>sqrt((double)i)) {A[primecount++]=i;}//如果j的值大于该数的平方根,说明该数是素数,将该数存入数组。
}
/*输出N以内的质数*/
for (i=0;i<primecount;i++)
{
cout<<setw(5)<<A[i];
if((i+1)%10==0) {cout<<endl;}
}
cout<<endl;
system("pause");
return 0;
}
/**************************************/