⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.cpp

📁 整理分享:常用的数学运算程序源代码 包括常用的几种数学运算程序的C++代码
💻 CPP
字号:
#include <stdio.h>
#include <string.h>
#include <fstream.h>

// 功能:实现buffer.h中的各个缓冲类的函数

#include "buffer.h"
#include "cbuffer.h"

DOUBLE defaulterr = 1e-8; 	// 缺省的误差调整值
int doadjust = 1;		// 决定数据是否根据误差值自动向整数靠扰,
							// 其实是向小数点后三位靠扰

/* 下面的六个指针分别初始化指向产生六个缓冲区长度为空的六个
	缓冲区,其中两个实数缓冲区,两个长整数缓冲区,两个复数缓冲区
  其中实数,长整数和复数这三种数据类型的每一种都有磁盘和内存两种
  缓冲区。如果数据较小时可以存放在内存中,而数据量很大时则存放在
  临时文件构成的磁盘缓冲区中。这六个空缓冲区并不真正用来存放数据,
  而是用来产生出新的与自己一样的缓冲区,因为它们都是抽象类buffer的
  子类,所以都将被settomemory函数或者settodisk函数赋给三个buffer类的
  指针,使得getnewbuffer,getnewcbuffer和getnewlbuffer三个函数能够从这些
  缓冲区中用抽象类函数产生同样类型的缓冲区。
  总的想法是,在以后编写的计算各种矩阵或者行列式,或者其它的大量
  数据的运算时,只要调用一次settomemroy或者settodisk函数,那么用户
  不必改写一行代码,就可以照算不误,而存储媒体已经改变。
*/
static membuffer *memorybuffer = new membuffer; // 实数内存缓冲区指针
static diskbuffer *diskfilebuffer = new diskbuffer; // 实数磁盘缓冲区指针
static lmembuffer *memorylbuffer = new lmembuffer; // 长整数内存缓冲区指针
static ldiskbuffer *diskfilelbuffer = new ldiskbuffer; // 长整数磁盘缓冲区指针
static memcbuffer *memorycbuffer = new memcbuffer; // 复数内存缓冲区指针
static diskcbuffer *diskfilecbuffer = new diskcbuffer; // 复数磁盘缓冲区指针


/* 以下三个缺省缓冲区指针为全局变量,用户可以定义自己的缓冲区
	类,并在产生静态实例变量后将其指针赋予它们 */

buffer *defbuffer = memorybuffer; // 缺省实数缓冲区指针
lbuffer *deflbuffer = memorylbuffer; // 缺省长整数缓冲区指针
cbuffer *defcbuffer = memorycbuffer; // 缺省复数缓冲区指针


/* 产生一个新的容量为n个实数的实数缓冲区,返回此缓冲区指针,
	缓冲区的类型与defbuffer指向的变量的子类类型相同 */
buffer * getnewbuffer(size_t n){
	return defbuffer->newbuf(n);
}

/* 产生一个新的容量为n个长整数的长整数缓冲区,返回此缓冲区指针,
	缓冲区的类型与deflbuffer指向的变量的子类类型相同 */
lbuffer * getnewlbuffer(size_t n){
	return deflbuffer->newbuf(n);
}

/* 产生一个新的容量为n个复数的复数缓冲区,返回此缓冲区指针,
	缓冲区的类型与defcbuffer指向的变量的子类类型相同 */
cbuffer * getnewcbuffer(size_t n){
	return defcbuffer->newbuf(n);
}

// 将各实数,长整数和复数的缺省的缓冲区指针指向相应的磁盘缓冲区指针
void settodisk()
{
	defbuffer = diskfilebuffer;
	deflbuffer = diskfilelbuffer;
	defcbuffer = diskfilecbuffer;
}

// 将各实数,长整数和复数的缺省的缓冲区指针指向相应的内存缓冲区指针
void settomemory()
{
	defbuffer = memorybuffer;
	deflbuffer = memorylbuffer;
	defcbuffer = memorycbuffer;
}

ostream& operator<<(ostream& o, buffer& b)
{
	size_t maxitem = 5;
	for(size_t i=0; i<b.len(); i++) {
		o << b[i] << '\t';
		if(((i+1) % maxitem)==0)
			o << endl;
	}
	o << endl;
	return o;
}


// 将实数缓冲区的第n个实数的值设为d,并返回一个实数缓冲区的
// 指针,此指针一般就是指向自己,而在一个缓冲区的引用数多于一个时
// 此函数将先克隆出一个新的缓冲区,此新的缓冲区的引用数为1,并对此
// 新的缓冲区的第n个实数的值设为d,然后返加新缓冲区的指针
buffer* buffer::set(size_t n, DOUBLE d)
{
	// 如调整标志设置,则调整
	if(doadjust) adjust(d);
	if(refnum == 1) {	// 如果引用数为1,则将第n个实数的值设为d,并返回自己
			// 的指针
		retrieve(n) = d;
		return this;
	}
	refnum --;	// 引用数大于1,因此将本缓冲区的引用数减1
	buffer * b;
	b = clone();	// 克隆一个内容同自己一样的新缓冲区
	(b->retrieve(n)) = d; // 将新缓冲区的第n个实数的值设为d
	return b;	// 返回新缓冲区的指针
}

buffer* membuffer::clone() // 克隆一个内容和自己一样的实数内存缓冲区,并返回其指针
{
	buffer* b;
	b = new membuffer(length);	// 建立一个新的实数内存缓冲区,尺寸和自己的一样
	if(length > 0)	// 如果自己有内容,将全部拷贝到新产生的缓冲区中
		for(size_t i=0; i<length; i++)
			(b->retrieve(i)) = (*this)[i];
	return b;
}

// 实数磁盘缓冲区构造函数
diskbuffer::diskbuffer(size_t lth):buffer(),length(lth),n(0)
{
	tempfp = tmpfile();	// 打开一新的临时文件,指针赋给tempfp
}

// 实数磁盘缓冲区的析构函数
diskbuffer::~diskbuffer()
{
	fclose(tempfp);	// 关闭临时文件
}

void diskbuffer::alloc(size_t num) // 将磁盘缓冲区重新定为尺寸为num
{
	length = num;
	if(!tempfp)	 // 如果临时文件尚未打开,则打开临时文件
		tempfp = tmpfile();
	n = 0;	// 当前缓冲区指针设在开始,就是0处
}

void diskbuffer::release() // 释放磁盘缓冲区
{
	fclose(tempfp);	// 关闭临时文件
	buf = 0.0;
	length = 0;
}

DOUBLE& diskbuffer::retrieve(size_t i) // 返回实数磁盘缓冲区的第i个实数
{
	long off;
	off = n*sizeof(DOUBLE); // 计算出当前指针n对应的文件的偏移量
	fseek(tempfp, off, SEEK_SET); // 移动文件指针到给定的偏移量处
	fwrite(&buf, sizeof(DOUBLE), 1, tempfp); // 将当前的buf中值写到文件中
	off = i*sizeof(DOUBLE); // 计算第i个实数在文件的什么位置
	fseek(tempfp, off, SEEK_SET); // 移动文件指针到给定的偏移量处
	fread(&buf, sizeof(DOUBLE), 1, tempfp); // 读回所需的实数值到buf中
	n = i;	// 并将n改为i
	return buf; // 返回读出的实数的引用
}

buffer* diskbuffer::clone() // 克隆一个新的内容与自己一样的实数磁盘缓冲区
{
	buffer* b;
	b = new diskbuffer(length); // 定位产生一个与自己长度一样的新缓冲区
	if(length > 0)	// 如果长度大于0,则自己的内容拷贝到新缓冲区
		for(size_t i=0; i<length; i++)
			(b->retrieve(i)) = (*this)[i];
	return b; // 返回新缓冲区的指针
}


// 将第n个长整数的值设为v,如果缓冲区的引用数大于1,
// 则会先克隆出新的缓冲区,然后再进行操作,并返回新缓冲区的指针
lbuffer* lbuffer::set(size_t n, long v)
{
	if(refnum == 1) { //  引用数为1
		retrieve(n) = v; // 将第n个长整数的值设为v
		return this;	// 返回自己
	}
	refnum --;		// 引用数大于1,引用数减1
	lbuffer * b;
	b = clone();	// 克隆出新的内容一样的长整数缓冲区
	(b->retrieve(n)) = v; // 将新缓冲区的第n个长整数值设为v
	return b;	// 返回新缓冲区的指针
}

ostream& operator<<(ostream& o, lbuffer& b)
{
	size_t maxitem = 5;
	for(size_t i=0; i<b.len(); i++) {
		o << b[i] << '\t';
		if(((i+1) % maxitem)==0)
			o << endl;
	}
	o << endl;
	return o;
}

lbuffer* lmembuffer::clone() // 克隆一个内容一新的长整数内存缓存区
{
	lbuffer* b;
	b = new lmembuffer(length);	// 产生长度与自己一样的长整数缓存区
	if(length > 0)	// 如果长度大于0,则将自己的内容拷贝过去
		for(size_t i=0; i<length; i++)
			(b->retrieve(i)) = (*this)[i];
	return b;	// 返回新缓存区的指针
}

// 长整数磁盘缓存区的构造函数
ldiskbuffer::ldiskbuffer(size_t lth):lbuffer(),length(lth),n(0)
{
	tempfp = tmpfile();	// 打开临时文件
}

// 长整数磁盘缓存区的析构函灵敏
ldiskbuffer::~ldiskbuffer()
{
	fclose(tempfp);	// 关闭临时文件
}

// 将长度定改为num
void ldiskbuffer::alloc(size_t num)
{
	length = num;
	if(!tempfp) // 如临时文件尚未打开,则打开
		tempfp = tmpfile();
	n = 0;
}

// 长整数磁盘缓存区释放
void ldiskbuffer::release()
{
	fclose(tempfp);	// 关闭临时文件
	buf = 0;
	length = 0;
}

// 检索第i个值的引用
long& ldiskbuffer::retrieve(size_t i)
{
	long off;
	off = n*sizeof(long); // 先将当前的内容保存
	fseek(tempfp, off, SEEK_SET);
	fwrite(&buf, sizeof(long), 1, tempfp);
	off = i*sizeof(long);	// 再取出第i个长整数到buf中
	fseek(tempfp, off, SEEK_SET);
	fread(&buf, sizeof(long), 1, tempfp);
	n = i;
	return buf;
}

// 克隆一个和内容和自己一样的长整数磁盘缓存区
lbuffer* ldiskbuffer::clone()
{
	lbuffer* b;
	b = new ldiskbuffer(length); // 产生长度和自己一样的缓存区
	if(length > 0)	// 如果自己内容不为空,拷贝内容到新的缓存区
		for(size_t i=0; i<length; i++)
			(b->retrieve(i)) = (*this)[i];
	return b;
}

DOUBLE adjust(DOUBLE & a) // 将实数调整为最靠近小数点后二位的实数
// 准则:如果一个实数距某个二位小数小于十的负八次幂,则调整为这个小数
// 否则不变
{
	DOUBLE b = floor(a*100.0+0.5)/100.0; // b是四舍五入到小数点后二位
	if(fabs(b-a)<defaulterr) // 如果舍入误差极小,则抛弃
		a = b;
	return a;
}

char * throwmessage(int l, char * f, char * c)
{
	static char a[100];
	sprintf(a,"file:%s,line:%d\nmessage:%s\n",f,l,c);
	return a;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -