C++程序设计趣题:类,模板

以下记录了笔者学习类、模板时遇到的有趣问题,在此记录下来便于回顾;并附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);
	}

【说明】
在内部定义的类ptXCArray3D::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;}
	

【说明】
无话可说。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值