📄 buffer.h
字号:
#ifndef BUFFER_H
#define BUFFER_H
// 功能:定义数据缓冲区各抽象类
#ifndef DOUBLE
#define DOUBLE double
// #define DOUBLE long double // 如double精度不够,则可将此行去注释,而将上行注释
// 即可得到更精确的结果
#endif // DOUBLE
#include <stdio.h>
extern DOUBLE defaulterr; // 缺省的误差标准,为十的负八次方
extern int doadjust; // 逻辑变量,为1则作调整,否则不作,缺省为1
DOUBLE adjust(DOUBLE & a); // 将实数调整为最靠近的小数点后二位数
class buffer // 定义抽象的双精度实数缓冲区类,此类以一维数组的形式专门存储大量的
// 双精度实数,而存储方式则由子类实现,即可以用内存,也可以用磁盘
// 空间,甚至服务器上的存储空间
{
public:
size_t refnum; // 引用数,一个缓冲区可能有多个矩阵同时引用它,
// 主要是在矩阵变量赋值导致多个矩阵具有同样的内容时
// 防止数据的大量拷贝,而引用数就说明现在有多少个
// 矩阵正在引用这个缓冲区
buffer():refnum(1){}; // 构造函数,预设引用数为1
// ~buffer(){};// 析构函数,释放缓冲区
virtual void alloc(size_t num)=0; // 申请容量为num的存储空间,或将缓冲区容量
//改为num,纯虚函数,子类必须实现
virtual void release()=0; // 释放占用的存储空间
virtual DOUBLE& retrieve(size_t n)=0; // 取出第n个双精度实型数据,n从0开始计算
virtual buffer* clone()=0; // 克隆出一个和自己类别一样,内容也一样的新的缓冲区,
// 为纯虚函数,子类必须实现
virtual buffer* newbuf(size_t n=0)=0; // 产生一个新的和自己类别一样的具有指定
// 尺寸的缓冲区,
DOUBLE & operator[](size_t n){ // 重载数组操作符(), 检索第n个字节的内容
return retrieve(n);};
virtual size_t len()=0; // 返回数组的长度,纯虚函数,必须由子类
// 实现
buffer* set(size_t n, DOUBLE d);
// 将实数缓冲区的第n个实数的值设为d,并返回一个实数缓冲区的
// 指针,此指针一般就是指向自己,而在一个缓冲区的引用数多于一个时
// 此函数将先克隆出一个新的缓冲区,此新的缓冲区的引用数为1,并对此
// 新的缓冲区的第n个实数的值设为d,然后返加新缓冲区的指针
friend ostream& operator<<(ostream& o, buffer& b);
};
ostream& operator<<(ostream& o, buffer& b);
buffer * getnewbuffer(size_t n=0); // 生成一个新的尺寸为n个实数的缓冲区,返回新产生的
// 缓冲区的指针,新产生的缓冲区的类别与下面的
// defbuffer指针指向的缓冲区的类别一致
extern buffer *defbuffer; // 指向buffer子类的变量,作为产生新的缓冲区的缺省类别
void settomemory(); // 将defbuffer指向内存类,这以后再调用getnewbuffer将产生内存类的
// 实数数组,即数组全部放在内存中
void settodisk(); // 将defbuffer指向磁盘类,这以后再调用getnewbuffer将产生数据存放在文件
// 中的实数数组,即数组全部放在数据文件中
class membuffer : public buffer // 一维的存放在内存中的双精度实数数组,请注意在DOS
// 操作系统下将受到64k内存段容量限制,而如果在win95以上
// 操作系统中用32位编译则没有这个限制。如果要在DOS下使用
// 扩展内存或扩充内存,可以另外编写buffer的子类
{
public:
DOUBLE *buf; // 指向存放双精度实数数据的内存缓冲区的指针
size_t length; // 数组的以实数个数计的长度
membuffer():buffer(),buf(0),length(0)// 构造函数,产生一个容量为0的实数缓冲区
{
};
membuffer(size_t lth):buffer(),length(lth)// 构造函数,产生长度为lth的实数缓冲区
{
if(lth>0)
buf=new DOUBLE[lth];
else
buf=0;
};
~membuffer()// 析构函数,释放缓冲区
{
delete buf;
}
void alloc(size_t num)// 将缓冲区的容量改为num个实数,原来的内容全部删去
{
delete []buf;
length = num;
buf = new DOUBLE[num];
};
DOUBLE& retrieve(size_t n)// 返回第n个字节,n的范围从0到length-1
{
return buf[n];
};
void release() // 释放内存,数组的长度变为0
{
delete []buf;
length = 0;
};
buffer* clone(); // 克隆自己
buffer* newbuf(size_t n=0)// 产生一个长度为n的与自己同类别的新缓冲区并返回相应的指针
{
return new membuffer(n);//在堆里创建一个membuffer类对象
};
size_t len(){return length;}; // 返回数组的长度
};
class diskbuffer : public buffer { // 磁盘实数缓冲区类,将实数数组存放在临时文件中
public:
DOUBLE buf; // 临时文件取出来的实数放在buf里
size_t length; // 缓冲区的长度,或者实数的个数
size_t n; // 当前的buf中存放的是第n个实数,也以此知道临时文件的当前指针位置
FILE * tempfp; // 指向临时文件的指针
diskbuffer():buffer(),buf(0.0),length(0),tempfp(0),n(0){}; // 缺省构造函数,产生长度为0的
// 磁盘实数缓冲区
diskbuffer(size_t lth); // 构造函数,产生长度为lth的磁盘实数缓冲区
~diskbuffer(); // 析构函数,关闭并删除临时文件
void alloc(size_t num); // 将缓冲区的尺寸重定为num
DOUBLE& retrieve(size_t n); // 检索出文件的第n个实数放在buf中并返回buf的引用
// 在检索之前先把当前的buf中的内容放回到文件中
void release(); // 释放空间
buffer* clone(); // 克隆自己
buffer* newbuf(size_t n=0){return new diskbuffer(n);}; // 产生一个新的磁盘实数缓冲区
size_t len(){return length;}; // 获得数组的长度
};
class lbuffer { // 长整数缓冲区的抽象基类,用来存放许多个长整数
// 继承的子类可以使用各种数据载体,如内存或者文件来存放长整数
public:
size_t refnum; // 缓冲区引用数,原理与buffer的相同
lbuffer():refnum(1){}; // 缺省构造函数
virtual void alloc(size_t num)=0; // 将缓冲区尺寸修改为num,原内容全部删去
virtual void release()=0; // 释放缓冲区
virtual long& retrieve(size_t n)=0; // 检索第n个元素,并返回引用
long & operator[](size_t n){ // 重载[]操作符,得到第n个元素,并返回引用
// 但这样调用有危险,要注意引用数为1时才可当左值
return retrieve(n);};
virtual lbuffer* clone()=0; // 克隆一个类别和内容与自己完全一样的长整数缓冲区
virtual lbuffer* newbuf(size_t n=0)=0; // 产生一个类别和自己一样的长整数缓冲区
virtual size_t len()=0; // 返回长度
lbuffer* set(size_t n, long v); // 设置第n个元素的值为v,n的范围是0到refnum-1
// 如引用数大于1,则会产生新的缓冲区进行操作
// 并返回新缓冲区指针
friend ostream& operator<<(ostream& o, lbuffer& b);
};
ostream& operator<<(ostream& o, lbuffer& b);
class lmembuffer : public lbuffer { // 内存长整数缓冲区,DOS系统将受到64K段限制
public:
long * buf; // 指向内存缓冲区的指针
size_t length; // 缓冲区长度
lmembuffer():lbuffer(),buf(0),length(0){}; // 缺省构造函数,长度为0
lmembuffer(size_t lth):lbuffer(),length(lth){ // 构造函数,lth为缓冲区长整数个数
buf = new long[lth]; };
~lmembuffer(){delete []buf;} // 析构函数,释放buf指向的内存
void alloc(size_t num){ // 将缓冲区长度修改为num,原内容消失
delete []buf;
length = num;
buf = new long[num]; };
long& retrieve(size_t n){ // 返回第n个长整数,n取值从0到length-1
return buf[n]; };
void release() { delete []buf; length = 0; }; // 释放内存,长度变为0
lbuffer* clone(); // 克隆一个内容完全一样的长整数缓冲区
lbuffer* newbuf(size_t n=0){return new lmembuffer(n);}; // 产生一个新的尺寸为n的缓冲区
size_t len(){return length;}; // 返回缓冲区的长度
};
class ldiskbuffer : public lbuffer { // 长整数磁盘缓冲区子类,将多个长整数存放在临时文件内
public:
long buf; // 当前的长整数
size_t length; // 缓冲区长度,以长整数个数为单位
size_t n; // buf中的内容是第n个元素的内容,n也说明了临时文件当前的指向
FILE * tempfp; // 临时文件指针
ldiskbuffer():lbuffer(),buf(0),length(0),tempfp(0),n(0){}; // 缺省构造函数,长度为0
ldiskbuffer(size_t lth); // 构造函数,lth为缓冲区长度
~ldiskbuffer(); // 析构函数,将关闭和删除临时文件
void alloc(size_t num); // 将缓冲区长度重新定为num
long& retrieve(size_t nn); // 检索第nn个元素放到buf中,在此之前先存放buf的内容到
// n的位置,再将文件的指针移到nn处取元素
void release(); // 释放存储空间
lbuffer* clone(); // 克隆一个内容完全一样的长整数磁盘缓冲区,但临时文件不同
lbuffer* newbuf(size_t nn=0){return new ldiskbuffer(nn);}; // 产生一个长度为nn的
// 长整数磁盘缓冲区子类变量,返回它的指针
size_t len(){return length;}; // 返回缓冲区长度
};
lbuffer * getnewlbuffer(size_t n=0); // 产生一个新的长整数缓冲区,子类的类别与下面的
// deflbuffer指向的缓冲区的类别相同
extern lbuffer *deflbuffer; // 缺省的长整数缓冲区指针
char * throwmessage(int l, char * f, char * c); // 产生错误信息字符串
#ifndef __LINE__
#define __LINE__ 0
#define __FILE__ "n"
#endif
// l为行号,f为文件名,c为出错信息,请不要直接调用,而是调用宏TMESSAGE
#define TMESSAGE(c) throwmessage(__LINE__,__FILE__,c)
#endif // BUFFER_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -