BUFFER.CPP
上传用户:wyp_nj
上传日期:2022-05-03
资源大小:484k
文件大小:8k
源码类别:

GPS编程

开发平台:

Visual C++

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <fstream.h>    
  4. #include <math.h>
  5. // 功能:实现buffer.h中的各个缓冲类的函数
  6. #include "buffer.h"
  7. DOUBLE defaulterr = 1e-8;  // 缺省的误差调整值
  8. int doadjust = 1; // 决定数据是否根据误差值自动向整数靠扰,
  9. // 其实是向小数点后三位靠扰
  10. /* 下面的六个指针分别初始化指向产生六个缓冲区长度为空的六个
  11. 缓冲区,其中两个实数缓冲区,两个长整数缓冲区,两个复数缓冲区
  12.   其中实数,长整数和复数这三种数据类型的每一种都有磁盘和内存两种
  13.   缓冲区。如果数据较小时可以存放在内存中,而数据量很大时则存放在
  14.   临时文件构成的磁盘缓冲区中。这六个空缓冲区并不真正用来存放数据,
  15.   而是用来产生出新的与自己一样的缓冲区,因为它们都是抽象类buffer的
  16.   子类,所以都将被settomemory函数或者settodisk函数赋给三个buffer类的
  17.   指针,使得getnewbuffer,getnewcbuffer和getnewlbuffer三个函数能够从这些
  18.   缓冲区中用抽象类函数产生同样类型的缓冲区。
  19.   总的想法是,在以后编写的计算各种矩阵或者行列式,或者其它的大量
  20.   数据的运算时,只要调用一次settomemroy或者settodisk函数,那么用户
  21.   不必改写一行代码,就可以照算不误,而存储媒体已经改变。
  22. */
  23. static membuffer *memorybuffer = new membuffer; // 实数内存缓冲区指针
  24. static diskbuffer *diskfilebuffer = new diskbuffer; // 实数磁盘缓冲区指针
  25. static lmembuffer *memorylbuffer = new lmembuffer; // 长整数内存缓冲区指针
  26. static ldiskbuffer *diskfilelbuffer = new ldiskbuffer; // 长整数磁盘缓冲区指针
  27. //static memcbuffer *memorycbuffer = new memcbuffer; // 复数内存缓冲区指针
  28. //static diskcbuffer *diskfilecbuffer = new diskcbuffer; // 复数磁盘缓冲区指针
  29. /* 以下三个缺省缓冲区指针为全局变量,用户可以定义自己的缓冲区
  30. 类,并在产生静态实例变量后将其指针赋予它们 */
  31. buffer *defbuffer = memorybuffer; // 缺省实数缓冲区指针
  32. lbuffer *deflbuffer = memorylbuffer; // 缺省长整数缓冲区指针
  33. //cbuffer *defcbuffer = memorycbuffer; // 缺省复数缓冲区指针
  34. /* 产生一个新的容量为n个实数的实数缓冲区,返回此缓冲区指针,
  35. 缓冲区的类型与defbuffer指向的变量的子类类型相同 */
  36. buffer * getnewbuffer(size_t n){
  37. return defbuffer->newbuf(n);
  38. }
  39. /* 产生一个新的容量为n个长整数的长整数缓冲区,返回此缓冲区指针,
  40. 缓冲区的类型与deflbuffer指向的变量的子类类型相同 */
  41. lbuffer * getnewlbuffer(size_t n){
  42. return deflbuffer->newbuf(n);
  43. }
  44. /* 产生一个新的容量为n个复数的复数缓冲区,返回此缓冲区指针,
  45. 缓冲区的类型与defcbuffer指向的变量的子类类型相同 */
  46. //cbuffer * getnewcbuffer(size_t n){
  47. // return defcbuffer->newbuf(n);
  48. //}
  49. // 将各实数,长整数和复数的缺省的缓冲区指针指向相应的磁盘缓冲区指针
  50. void settodisk()
  51. {
  52. defbuffer = diskfilebuffer;
  53. deflbuffer = diskfilelbuffer;
  54. // defcbuffer = diskfilecbuffer;
  55. }
  56. // 将各实数,长整数和复数的缺省的缓冲区指针指向相应的内存缓冲区指针
  57. void settomemory()
  58. {
  59. defbuffer = memorybuffer;
  60. deflbuffer = memorylbuffer;
  61. // defcbuffer = memorycbuffer;
  62. }
  63. ////   ////
  64. /*ostream& operator<<(ostream& o, buffer& b)
  65. {
  66. size_t maxitem = 5;
  67. for(size_t i=0; i<b.len(); i++) {
  68. o << b[i] << 't';
  69. if(((i+1) % maxitem)==0)
  70. o << endl;
  71. }
  72. o << endl;
  73. return o;
  74. }
  75. */
  76. // 将实数缓冲区的第n个实数的值设为d,并返回一个实数缓冲区的
  77. // 指针,此指针一般就是指向自己,而在一个缓冲区的引用数多于一个时
  78. // 此函数将先克隆出一个新的缓冲区,此新的缓冲区的引用数为1,并对此
  79. // 新的缓冲区的第n个实数的值设为d,然后返加新缓冲区的指针
  80. buffer* buffer::set(size_t n, DOUBLE d)
  81. {
  82. // 如调整标志设置,则调整
  83. if(doadjust) adjust(d);
  84. if(refnum == 1) { // 如果引用数为1,则将第n个实数的值设为d,并返回自己
  85. // 的指针
  86. retrieve(n) = d;
  87. return this;
  88. }
  89. refnum --; // 引用数大于1,因此将本缓冲区的引用数减1
  90. buffer * b;
  91. b = clone(); // 克隆一个内容同自己一样的新缓冲区
  92. (b->retrieve(n)) = d; // 将新缓冲区的第n个实数的值设为d
  93. return b; // 返回新缓冲区的指针
  94. }
  95. buffer* membuffer::clone() // 克隆一个内容和自己一样的实数内存缓冲区,并返回其指针
  96. {
  97. buffer* b;
  98. b = new membuffer(length); // 建立一个新的实数内存缓冲区,尺寸和自己的一样
  99. if(length > 0) // 如果自己有内容,将全部拷贝到新产生的缓冲区中
  100. for(size_t i=0; i<length; i++)
  101. (b->retrieve(i)) = (*this)[i];
  102. return b;
  103. }
  104. // 实数磁盘缓冲区构造函数
  105. diskbuffer::diskbuffer(size_t lth):buffer(),length(lth),n(0)
  106. {
  107.    tempfp = tmpfile(); // 打开一新的临时文件,指针赋给tempfp
  108. ////if ( (tempfp =fopen( "tmpdata", "w+" )) == NULL ) //EVC
  109. //exit(1);                                            //EVC
  110. }
  111. // 实数磁盘缓冲区的析构函数
  112. diskbuffer::~diskbuffer()
  113. {
  114. fclose(tempfp); // 关闭临时文件
  115. }
  116. void diskbuffer::alloc(size_t num) // 将磁盘缓冲区重新定为尺寸为num
  117. {
  118. length = num;
  119. if(!tempfp)  // 如果临时文件尚未打开,则打开临时文件
  120.   tempfp = tmpfile();
  121.  ////if ( (tempfp =fopen( "tmpdata", "w+" )) == NULL ) //EVC
  122. ////  exit(1);                                       //EVC
  123. n = 0; // 当前缓冲区指针设在开始,就是0处
  124. }
  125. void diskbuffer::release() // 释放磁盘缓冲区
  126. {
  127. fclose(tempfp); // 关闭临时文件
  128. buf = 0.0;
  129. length = 0;
  130. }
  131. DOUBLE& diskbuffer::retrieve(size_t i) // 返回实数磁盘缓冲区的第i个实数
  132. {
  133. long off;
  134. off = n*sizeof(DOUBLE); // 计算出当前指针n对应的文件的偏移量
  135. fseek(tempfp, off, SEEK_SET); // 移动文件指针到给定的偏移量处
  136. fwrite(&buf, sizeof(DOUBLE), 1, tempfp); // 将当前的buf中值写到文件中
  137. off = i*sizeof(DOUBLE); // 计算第i个实数在文件的什么位置
  138. fseek(tempfp, off, SEEK_SET); // 移动文件指针到给定的偏移量处
  139. fread(&buf, sizeof(DOUBLE), 1, tempfp); // 读回所需的实数值到buf中
  140. n = i; // 并将n改为i
  141. return buf; // 返回读出的实数的引用
  142. }
  143. buffer* diskbuffer::clone() // 克隆一个新的内容与自己一样的实数磁盘缓冲区
  144. {
  145. buffer* b;
  146. b = new diskbuffer(length); // 定位产生一个与自己长度一样的新缓冲区
  147. if(length > 0) // 如果长度大于0,则自己的内容拷贝到新缓冲区
  148. for(size_t i=0; i<length; i++)
  149. (b->retrieve(i)) = (*this)[i];
  150. return b; // 返回新缓冲区的指针
  151. }
  152. // 将第n个长整数的值设为v,如果缓冲区的引用数大于1,
  153. // 则会先克隆出新的缓冲区,然后再进行操作,并返回新缓冲区的指针
  154. lbuffer* lbuffer::set(size_t n, long v)
  155. {
  156. if(refnum == 1) { //  引用数为1
  157. retrieve(n) = v; // 将第n个长整数的值设为v
  158. return this; // 返回自己
  159. }
  160. refnum --; // 引用数大于1,引用数减1
  161. lbuffer * b;
  162. b = clone(); // 克隆出新的内容一样的长整数缓冲区
  163. (b->retrieve(n)) = v; // 将新缓冲区的第n个长整数值设为v
  164. return b; // 返回新缓冲区的指针
  165. }
  166. ////   ////
  167. /*ostream& operator<<(ostream& o, lbuffer& b)
  168. {
  169. size_t maxitem = 5;
  170. for(size_t i=0; i<b.len(); i++) {
  171. o << b[i] << 't';
  172. if(((i+1) % maxitem)==0)
  173. o << endl;
  174. }
  175. o << endl;
  176. return o;
  177. }
  178. */
  179. lbuffer* lmembuffer::clone() // 克隆一个内容一新的长整数内存缓存区
  180. {
  181. lbuffer* b;
  182. b = new lmembuffer(length); // 产生长度与自己一样的长整数缓存区
  183. if(length > 0) // 如果长度大于0,则将自己的内容拷贝过去
  184. for(size_t i=0; i<length; i++)
  185. (b->retrieve(i)) = (*this)[i];
  186. return b; // 返回新缓存区的指针
  187. }
  188. // 长整数磁盘缓存区的构造函数
  189. ldiskbuffer::ldiskbuffer(size_t lth):lbuffer(),length(lth),n(0)
  190. {
  191.  tempfp = tmpfile(); // 打开临时文件
  192. ////if ( (tempfp =fopen( "tmpdatal", "w+" )) == NULL )  //EVC
  193. ////   exit(1);                                        //EVC
  194. }
  195. // 长整数磁盘缓存区的析构函灵敏
  196. ldiskbuffer::~ldiskbuffer()
  197. {
  198. fclose(tempfp); // 关闭临时文件
  199. }
  200. // 将长度定改为num
  201. void ldiskbuffer::alloc(size_t num)
  202. {
  203. length = num;
  204. if(!tempfp) // 如临时文件尚未打开,则打开
  205.     tempfp = tmpfile();
  206. //// if ( (tempfp =fopen( "tmpdatal", "w+" )) == NULL ) //EVC
  207. //// exit(1);                                           //EVC
  208. n = 0;
  209. }
  210. // 长整数磁盘缓存区释放
  211. void ldiskbuffer::release()
  212. {
  213. fclose(tempfp); // 关闭临时文件
  214. buf = 0;
  215. length = 0;
  216. }
  217. // 检索第i个值的引用
  218. long& ldiskbuffer::retrieve(size_t i)
  219. {
  220. long off;
  221. off = n*sizeof(long); // 先将当前的内容保存
  222. fseek(tempfp, off, SEEK_SET);
  223. fwrite(&buf, sizeof(long), 1, tempfp);
  224. off = i*sizeof(long); // 再取出第i个长整数到buf中
  225. fseek(tempfp, off, SEEK_SET);
  226. fread(&buf, sizeof(long), 1, tempfp);
  227. n = i;
  228. return buf;
  229. }
  230. // 克隆一个和内容和自己一样的长整数磁盘缓存区
  231. lbuffer* ldiskbuffer::clone()
  232. {
  233. lbuffer* b;
  234. b = new ldiskbuffer(length); // 产生长度和自己一样的缓存区
  235. if(length > 0) // 如果自己内容不为空,拷贝内容到新的缓存区
  236. for(size_t i=0; i<length; i++)
  237. (b->retrieve(i)) = (*this)[i];
  238. return b;
  239. }
  240. DOUBLE adjust(DOUBLE & a) // 将实数调整为最靠近小数点后二位的实数
  241. // 准则:如果一个实数距某个二位小数小于十的负八次幂,则调整为这个小数
  242. // 否则不变
  243. {
  244. DOUBLE b = floor(a*100.0+0.5)/100.0; // b是四舍五入到小数点后二位
  245. if(fabs(b-a)<defaulterr) // 如果舍入误差极小,则抛弃
  246. a = b;
  247. return a;
  248. }
  249. char * throwmessage(int l, char * f, char * c)
  250. {
  251. static char a[100];
  252. sprintf(a,"file:%s,line:%dnmessage:%sn",f,l,c);
  253. return a;
  254. }