ep9_11.cpp
上传用户:wxcui2006
上传日期:2022-07-12
资源大小:1274k
文件大小:6k
源码类别:

书籍源码

开发平台:

Visual C++

  1. /*9.11 正弦函数在0o~90o的范围中是单调递增的,建立两个文件:一个放sin0o,sin2o,…,sin80o;
  2. 另一个放sin1o,sin3o,…,sin79o, sin81o,sin82o,…,sin90o,用归并法,把这两个数据文件合并
  3. 为升序排序的文件,重组为一个完整的sin()函数表文件。*/
  4. //题解中注释掉的直接读写法与使用成员函数结果完全相同,对于类对象,读和写及占据内存大小均指数据成员, .   仅
  5. #include<cmath>
  6. #include<fstream>
  7. #include<iostream>
  8. #include<iomanip>
  9. using namespace std;
  10. class sinx{
  11. double Degree;//角度
  12. double Value;//正弦值
  13. public:
  14. sinx(double =0);
  15. void display();
  16. void Bdatatofile(fstream &);   //流类作为形式参数必须是引用
  17. void Bdatafromfile(fstream &);
  18. void datainput(double deg);
  19. bool operator<=(sinx &);
  20. bool operator==(sinx &);
  21. };
  22. bool sinx::operator<=(sinx & si){
  23. double k;
  24. k=Degree-si.Degree;
  25. if(k<=0) return true;
  26. else return false;
  27. }
  28. bool sinx::operator==(sinx & si){
  29. double k;
  30. k=Degree-si.Degree;
  31. if(k==0) return true;
  32. else return false;
  33. }
  34. sinx::sinx(double deg){
  35. Degree=deg;
  36. Value=sin(deg*3.1415926535/180);
  37. }
  38. void sinx::display(){
  39. cout<<setw(10)<<Degree<<setw(10)<<Value<<endl;
  40. }
  41. void sinx::datainput(double deg){
  42. Degree=deg;
  43. Value=sin(deg*3.1415926535/180);
  44. }
  45. void sinx::Bdatatofile(fstream & dest){
  46. dest.write((char*)&Degree,sizeof(double));
  47. dest.write((char*)&Value,sizeof(double));
  48. }
  49. void sinx::Bdatafromfile(fstream & sour){
  50. sour.read((char*)&Degree,sizeof(double));
  51. sour.read((char*)&Value,sizeof(double));
  52. }//由此可见读和写是完全对称的过程,次序决不能错
  53. template <typename T>class Array{
  54. T *elements;
  55. char name[20];
  56. int Subscript;//已用最大下标值
  57. int maxSize;
  58. fstream datafile;
  59. public:
  60. Array(char* ="myfile",int=20);
  61. ~Array();
  62. bool IsFull() const{return Subscript==maxSize-1;}
  63. void renews();//数组扩大一倍
  64. void ordinsert(T&);//升序输入
  65. void listshow();//显示数组
  66. };
  67. template <typename T> Array<T>::Array(char* filename,int maxs){
  68. maxSize=maxs;
  69. Subscript=-1;//私有数据不容许直接赋初值,必须在构造函数中赋初值
  70. strcpy(name,filename);
  71. T temp;
  72. elements=new T[maxSize];
  73. datafile.open(name,ios::binary|ios::in);
  74. if(!datafile==0){
  75. while(!datafile.eof()){
  76. temp.Bdatafromfile(datafile);
  77. // datafile.read((char*)&temp,sizeof(T));//直接读写法与使用成员函数结果完全相同
  78. if(datafile.eof()==0){//读到无数据可读后,即读入不成功,eofbit为1
  79. ordinsert(temp);
  80. }
  81. }
  82. datafile.close();
  83. }
  84. datafile.clear(0);//采用标准库不可少,前面读到过文件结束或打开文件失败,无法恢复
  85. }
  86. template <typename T> Array<T>::~Array(){
  87. int i;
  88. datafile.open(name,ios::binary|ios::out);
  89. for(i=0;i<=Subscript;i++)
  90. elements[i].Bdatatofile(datafile);
  91. // datafile.write((char*)&elements[i],sizeof(T));//直接读写法与使用成员函数结果完全相同
  92. datafile.close();
  93. delete[]elements;
  94. }
  95. template <typename T> void Array<T>::renews(){
  96. int i;
  97. T *temp=elements;
  98. maxSize*=2;
  99. elements=new T[maxSize];
  100. for(i=0;i<=Subscript;i++) elements[i]=temp[i];
  101. delete[]temp;
  102. }
  103. template <typename T> void Array<T>::ordinsert(T & elem){//以角度为关键字排序
  104. int i,j;
  105. if(IsFull()) renews();
  106. for(i=0;i<=Subscript;i++) if(elem<=elements[i]) break;
  107. if(!(elem==elements[i])){
  108. for(j=Subscript;j>=i;j--) elements[j+1]=elements[j];
  109. Subscript++;
  110. }
  111. if(Subscript==-1) Subscript++;//考虑到进入的第一项
  112. elements[i]=elem;
  113. }
  114. template <typename T> void Array<T>::listshow(){
  115. int i;
  116. for(i=0;i<=Subscript;i++) elements[i].display();
  117. }
  118. //两个文件归并用独立的函数模板
  119. template <typename T> void Merge(char*filename1,char*filename2,char*filename){
  120. fstream sdatafile1(filename1,ios::out|ios::in|ios::binary);
  121. fstream sdatafile2(filename2,ios::out|ios::in|ios::binary);
  122. fstream ddatafile(filename,ios::out|ios::binary);
  123. int i=0,j=0,k=0,ns1,ns2;
  124. T temps1,temps2;
  125. while(sdatafile1.eof()==0){//侧元素数量,注意会多出一个
  126. sdatafile1.read((char*)&temps1,sizeof(T));
  127. i++;
  128. }
  129. ns1=i-1;
  130. cout<<"表1元素数"<<ns1<<endl;
  131. while(sdatafile2.eof()==0){
  132. sdatafile2.read((char*)&temps2,sizeof(T));
  133. j++;
  134. }
  135. ns2=j-1;
  136. cout<<"表2元素数"<<ns2<<endl;
  137. sdatafile1.clear(0);//用随机方式,一旦用顺序文件方式访问到结束,就必须清状态
  138. sdatafile2.clear(0);
  139.     i=0;
  140. j=0;
  141. sdatafile1.seekg(0,ios::beg);
  142. sdatafile2.seekg(0,ios::beg);
  143. // sdatafile1.read((char*)&temps1,sizeof(T));//此方法与用成员函数完全相同
  144. // sdatafile2.read((char*)&temps2,sizeof(T));//对于类对象,读和写及大小均仅指数据成员
  145. temps1.Bdatafromfile(sdatafile1);
  146. temps2.Bdatafromfile(sdatafile2);
  147. while(i<ns1&&j<ns2){
  148. if(temps1<=temps2){
  149. // ddatafile.write((char*)&temps1,sizeof(T));
  150. // sdatafile1.read((char*)&temps1,sizeof(T));
  151. temps1.Bdatatofile(ddatafile);
  152. temps1.Bdatafromfile(sdatafile1);
  153. i++;
  154. }
  155. else{
  156. // ddatafile.write((char*)&temps2,sizeof(T));//对于类对象,读和写及大小均仅指数据成员
  157. // sdatafile2.read((char*)&temps2,sizeof(T));//此方法与用成员函数完全相同
  158. temps2.Bdatatofile(ddatafile);
  159. temps2.Bdatafromfile(sdatafile2);
  160. j++;
  161. }
  162. }
  163. while(i<ns1){//复制第一个表的剩余元素
  164. // ddatafile.write((char*)&temps1,sizeof(T));
  165. // sdatafile1.read((char*)&temps1,sizeof(T));
  166. temps1.Bdatatofile(ddatafile);
  167. temps1.Bdatafromfile(sdatafile1);
  168. i++;
  169. }
  170. while(j<ns2){//复制第二个表的剩余元素
  171. // ddatafile.write((char*)&temps2,sizeof(T));
  172. // sdatafile2.read((char*)&temps2,sizeof(T));
  173. temps2.Bdatatofile(ddatafile);
  174. temps2.Bdatafromfile(sdatafile2);
  175. j++;
  176. }
  177. sdatafile1.close();
  178. sdatafile2.close();
  179. ddatafile.close();
  180. }
  181. int main(){
  182. sinx temp;
  183. int i;
  184. {//两个正弦表分别在两个块域中定义,域结束时对象存入文件
  185. Array<sinx> mylist("mydata1");
  186. cout<<"建立正弦表1(0,2,4,~80度)"<<endl;
  187. for(i=0;i<=80;i=i+2){
  188. temp.datainput(i);
  189. mylist.ordinsert(temp);//除排序外,同时保证二次进入时不会有重复的表项
  190. }
  191. mylist.listshow();
  192. }
  193. {
  194. Array<sinx> mylist("mydata2");
  195.         cout<<"建立正弦表2(1,3,5,~81度;82,83,~90)"<<endl;
  196. for(i=82;i<=90;i++){
  197. temp.datainput(i);
  198. mylist.ordinsert(temp);
  199. }
  200. for(i=1;i<=81;i=i+2){//注意较小的数后入
  201. temp.datainput(i);
  202. mylist.ordinsert(temp);
  203. }
  204. mylist.listshow();
  205. }
  206.     Merge<sinx>("mydata1","mydata2","mydata");//按题意要求两个文件归并直接使用文件
  207. Array<sinx> mylist("mydata");
  208. cout<<"输出正弦表(0,1,~90度)"<<endl;
  209. mylist.listshow();
  210. return 0;
  211. }