以下记录了笔者学习类、模板时遇到的有趣问题,在此记录下来便于回顾;并附AC的自编代码段,欢迎大家批评建议。
目录
例题一 “很难蒙混过关的CArray3d三维数组模板类”
例题二 “我自己的 ostream_iterator”
例题一 “很难蒙混过关的CArray3d三维数组模板类”
【描述】
实现一个三维数组模版CArray3D,可以用来生成元素为任意类型变量的三维数组,输出指定结果。
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
template <class T>
class CArray3D
{
//***********************************
//********在此处补充你的代码*********
//***********************************
};
CArray3D<int> a(3,4,5);
CArray3D<double> b(3,2,2);
void PrintA()
{
for(int i = 0;i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 4; ++j) {
for(int k = 0; k < 5; ++k)
cout << a[i][j][k] << "," ;
cout << endl;
}
}
}
void PrintB()
{
for(int i = 0;i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 2; ++j) {
for(int k = 0; k < 2; ++k)
cout << b[i][j][k] << "," ;
cout << endl;
}
}
}
int main()
{
int No = 0;
for( int i = 0; i < 3; ++ i ) {
a[i];
for( int j = 0; j < 4; ++j ) {
a[j][i];
for( int k = 0; k < 5; ++k )
a[i][j][k] = No ++;
a[j][i][i];
}
}
PrintA();
memset(a[1],-1 ,20*sizeof(int));
memset(a[1],-1 ,20*sizeof(int));
PrintA();
memset(a[1][1],0 ,5*sizeof(int));
PrintA();
for( int i = 0; i < 3; ++ i )
for( int j = 0; j < 2; ++j )
for( int k = 0; k < 2; ++k )
b[i][j][k] = 10.0/(i+j+k+1);
PrintB();
int n = a[0][1][2];
double f = b[0][1][1];
cout << "****" << endl;
cout << n << "," << f << endl;
return 0;
}
【样例输入】
无
【样例输出】
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
20,21,22,23,24,
25,26,27,28,29,
30,31,32,33,34,
35,36,37,38,39,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
-1,-1,-1,-1,-1,
0,0,0,0,0,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
10,5,
5,3.33333,
layer 1:
5,3.33333,
3.33333,2.5,
layer 2:
3.33333,2.5,
2.5,2,
****
7,3.33333
【来源】OJ
【注】
此题的主要困难在于不能直接对指针变量T***
分配三维动态数组,否则各个一维数组在内存中不连续存储,语句
memset(a[1],-1 ,20*sizeof(int));
memset(a[1],-1 ,20*sizeof(int));
会报错。必须要一次性分配一整片区域给一维指针。但如何合理地重载operator[]
以兼容CArray3D::a[i][j][k]
又会成为问题。
【自编代码】
T* pt;
int x, y, z;
class ptX;
class ptX {
public:
T* ptx;
int zz;
ptX(T* ptx_, int zz_) :ptx(ptx_),zz(zz_) { ; }
T* operator[](int n) { return ptx + n * zz; }//
operator void* () { return reinterpret_cast<void*>(ptx); }
};
public:
CArray3D(int x_, int y_, int z_ ):
x(x_),y(y_),z(z_)
{
pt = new T[x*y*z];
return;
}
ptX operator[](int n) {
return ptX(pt + n*y*z,z);
}
【说明】
在内部定义的类ptX
作CArray3D::operator[]
的返回值,起到中继的作用。同时为了兼容语句
memset(a[1],-1 ,20*sizeof(int));
还需要重载强制类型转换运算符:
ptX::operator void* () { return reinterpret_cast<void*>(ptx); }
如果有实际应用还应该写带delete[]
的析构函数,此处省略。
例题二 “我自己的 ostream_iterator”
【描述】
程序填空输出指定结果
#include <iostream>
#include <list>
#include <string>
using namespace std;
template <class T1,class T2>
void Copy(T1 s,T1 e, T2 x)
{
for(; s != e; ++s,++x)
*x = *s;
}
template<class T>
class myostream_iteraotr
{
//********************************
//*******在此处补充你的代码*******
//********************************
};
int main()
{ const int SIZE = 5;
int a[SIZE] = {5,21,14,2,3};
double b[SIZE] = { 1.4, 5.56,3.2,98.3,3.3};
list<int> lst(a,a+SIZE);
myostream_iteraotr<int> output(cout,",");
Copy( lst.begin(),lst.end(),output);
cout << endl;
myostream_iteraotr<double> output2(cout,"--");
Copy(b,b+SIZE,output2);
return 0;
}
【输入】
无
【输出】
5,21,14,2,3,
1.4–5.56–3.2–98.3–3.3–
【来源】OJ
【注】
一开始以为要在自己写的类中包含一个list<T>::iterator
对象,后来发现想多了。
需要重载operator*()
和operator++()
,还需要在恰当的时机输出。
【自编代码】
T* itr;
ostream& os;
string mid;
public:
myostream_iteraotr(ostream& os_, const string mid_)
:os(os_), mid(mid_), itr(NULL) { itr = new T;*itr=0 ; }
T& operator*() { return *itr; }
void operator++() {if(itr)os << *itr << mid;}
【说明】
无话可说。