第四章作业补+排序+查询

main主程序中
#include <iostream>
#include "sclass4_11_Node.h"

int CNode::sNodeNum=0;

void main()
{
	int now;
	int k;
	cout<<"1*************************************************."<<endl;//主要观察拷贝构造函数和new以及delete的作用
	CNodeArray oCNA1;
	{//内部作用域,去掉注释可观察到oCN1和oCN2的析构位置
		int i;
		char s[81];//存放暂时获取的结点名字
		string str;
		//CNode oCN1("Zhang San"),oCN2("Li Si");
		//oCN2=oCN1;//调用重载的赋值运算符
		CNode *poCN1,*poCN2;//定义一个CNode指针
		for(i=0;i<5;i++)
		{
			cout<<"Input a Node Name or word\"stop\":";
			cin.getline(s,81,'\n');//输入字符串作为结点名,str=gets(s);
			str=s;
			if(str=="stop")
				break;
			poCN1=new CNode(str);//调用一般构造函数新建对象
		//	poCN2=new CNode(*poCN1);//调用拷贝构造函数新建对象&*poCN1=poCN1传入的是它的地址,它本身参数引用输入
		//	cout<<oCNA1[0]<<endl;
		//	cout<<*(oCNA1[0].GetStr())<<endl;
			
			oCNA1.Insert(*poCN1);
		//	oCNA1.Insert(*poCN2);
			cout<<"aIndex="<<oCNA1.GetaIndex()<<endl;
		}
		cout<<"***********"<<endl;
		//查找 
		cout<<"要查找含该字符串的结点位置"<<endl;
		string  look;
		cin>>look;
		for(int f=0;f<oCNA1.GetaIndex();f++)
		{
			if(look==*(oCNA1[f].GetStr()))
			{
				cout<<"************No:"<<f<<endl;
			}
		}
		//排序
		for(int j=0;j<oCNA1.GetaIndex()-1;j++)
		{
			cout<<"j="<<j<<endl;
			//cout<<"aIndex="<<oCNA1.GetaIndex()<<endl;
			cout<<"第一步"<<endl;
			for(now=j,k=j+1;k<oCNA1.GetaIndex();k++)
			{
				cout<<"k="<<k<<endl;
				cout<<"第二步"<<endl;
				if((*(oCNA1[k].GetStr()))<(*(oCNA1[now].GetStr())))
				{
					now=k;
					cout<<"最小的下标为:now="<<now<<endl;
				}
			}
			if(now!=j)
			{
				string temp=*(oCNA1[now].GetStr());
				str=*(oCNA1[j].GetStr());
				poCN1=new CNode(str);
				oCNA1.Insert(*poCN1,now);
				str=temp;
				poCN1=new CNode(str);
				oCNA1.Insert(*poCN1,j);
			}
		}
		cout<<"排序结果是:"<<endl;
		cout<<"*(oCNA1[0].GetStr())"<<*(oCNA1[0].GetStr())<<endl;
		cout<<"*(oCNA1[1].GetStr())"<<*(oCNA1[1].GetStr())<<endl;
		cout<<"*(oCNA1[2].GetStr())"<<*(oCNA1[2].GetStr())<<endl;
		cout<<"排序结束"<<endl;
	}

	/*cout<<"*****START*************************************."<<endl;
	cout<<oCNA1[0];//观察重载运算符的"<<"和"[]"运算符,其中在<<中值传入参数时创建了一个obj的对象,所以创建一个拷贝构造函数,然后当函数结束时,自动的析构它
	cout<<"*****END***************************************."<<endl;
	for(int i=0;i<5;i++)
	{
		oCNA1.Delete(i);//注释掉本语句可观察到delete的作用
	}
	cout<<"2**********************************************."<<endl;
	//第二段作用域主要观察重载的new和delete的调用
	{
		CNode oCN1("Genghis kahan");
		CNodeArray *poCN3=new CNodeArray;//调用重载“new”
		//cout<<"111"<<endl;
		delete poCN3;//调用重载delete,通过:delete可调用系统delete//为什么当使用delete的时候CNodeArray函数才析构
		//cout<<"123"<<endl;
	}
	cout<<"3**********************************************."<<endl;
	{//第三段作用域主要观察《》,=等运算符的重载
		CNode oCN1("Genghis khan"),oCN2("11"),oCN3(oCN1);
		cin>>oCN3;
		cout<<oCN3;
		oCN3=oCN2,oCN1;
		cout<<oCN3;
	}*/

}
sclass——cnode.cpp
#include "sclass4_11_Node.h"
CNode::CNode(string str)
{
	m_pStr=new string(str);
	if(NULL==m_pStr)
	{
		cout<<"内存分配失败"<<endl;
		exit(0);//内存分配失败,直接退出了程序
	}
	m_nodeNum=GetNumber();
	cout<<"CNode全新创建结点,No:"<<m_nodeNum<<",Name:"<<*m_pStr<<endl;
}
CNode::CNode(const CNode &oCN)//拷贝构造函数的参数只有一个,就是同类的其他对象的引用,且不可修改(其参数通常是同一类的const对象),拷贝构造函数必须以引用的形式传递参数的原因是,当一个对象以传递值的方式传入一个函数时,将自动调用拷贝构造;如果一个对象时被传入自己的拷贝构造函数,也将调用它的拷贝构造函数;而函数返回对象时也需要调用拷贝构造函数,这样就可能引起无线循环,而采用引用可以避免这种情况的发生
{
	m_pStr=new string (*oCN.m_pStr);//oCN是一个对象而oCN.m_pStr是一个指针,外面再加*表示指向这个对象里面的指针指向的内容
	if(m_pStr==NULL)
	{
		cout<<"内存分配失败。"<<endl;
		exit(0);
	}
	m_nodeNum=GetNumber();//取得结点编号,并赋值给m_nodeNum;
	cout<<"CNode拷贝创建结点,No:"<<m_nodeNum<<",Name:"<<*m_pStr<<endl;
}
CNode::~CNode()
{
	cout<<"~CNode销毁结点,No:"<<m_nodeNum<<",Name"<<*m_pStr<<endl;
	delete m_pStr;
}
CNode &CNode::operator =(const CNode &oCN)
{
	if(this==&oCN)
	{
		return *this;
	}
	delete m_pStr;
	m_pStr=new string(*oCN.m_pStr);
	if(NULL==m_pStr)
	{
		cout<<"内存分配失败。"<<endl;
		exit(0);
	}
	m_nodeNum=oCN.m_nodeNum;
	cout<<"CNode复制了对象,No:"<<m_nodeNum<<",Name:"<<*m_pStr<<endl;
	return *this;
}

const CNode &CNode::operator ,(const CNode &oCN)
{
	return oCN;//直接返回第二操作数
}

ostream& operator<<(ostream& scout,CNode& obj)
{
	scout<<"Node Name:"<<*(obj.GetStr())<<",";//若用户自定义的ostream中的引用scout,则也可以使用《
	scout<<"Node Number:"<<obj.GetNodeNum()<<"."<<endl;
	return scout;//ostream类型返回scout
}

istream& operator>>(istream& scin,CNode& obj)
{
	char s[81];
	cout<<"please Enter Node Name:";
	scin.getline(s,81,'\n');//getline(scin,*(obj.GetStr()))
	*(obj.GetStr())=(string)s;//s转化为string对象后再赋值
	cout<<"Please Enter Node Number:";
	scin>>obj.GetNodeNum();
	return scin;//istream类型返回scin
}

int CNode::GetNumber(void)
{
	return sNodeNum<LEN?sNodeNum++:(sNodeNum=0);
}
string *CNode::GetStr()
{
	return m_pStr;
}
int &CNode::GetNodeNum()
{
	return m_nodeNum;
}

CNodeArray::CNodeArray(int aLength)//构造时将指针全部初始化,指向NULL
{
	for(int i=0;i<aLength;i++)
	{
		m_poCN[i]=NULL;
	}
	m_aLength=aLength;
	m_aIndex=0;//当前结点下标设置为0
	cout<<"CNodeArray,创建一个结点数组对象,length=:"<<m_aLength<<endl;
}
CNodeArray::~CNodeArray(void)//~CNodeArray析构函数,确认m_poCN指向的对象的指针所指向的空间是否析构了
{
	for(int i=0;i<m_aIndex;i++)
	{
		if(m_poCN[i]!=NULL)
		{
			delete m_poCN[i];
			cout<<"delete:m_poCN["<<i<<"]."<<endl;
		}
	}
	cout<<"~CNodeArray:析构完成."<<endl;
}
//这里设计了很简单的结点插入功能,即只是让数组的CNode指针指向新结点而已。
//为了安全起见,先对插入位置坐判断,如果原来有结点,报插入失败,返回
bool CNodeArray::Insert(CNode &oCN)
{
	if(m_aIndex>=m_aLength)
	{
		cout<<"对不起,超过了数组最大下标,不可再插入!"<<endl;
		return false;
	}
	if(m_poCN[m_aIndex]!=NULL)
	{
		cout<<"此位置已有结点,不可再插入!"<<endl;
		return false;
	}
	m_poCN[m_aIndex]=&oCN;//重载运算符
	cout<<"插入新结点,Pos:"<<m_aIndex<<",No:"<<oCN.GetNodeNum()<<",Name:"<<*oCN.GetStr()<<endl;
	m_aIndex++;
	return true;
}
void CNodeArray::Insert(CNode &oCN,int i)
{
	if(i>=m_aLength)
	{
		cout<<"对不起,超过了数组最大下标,不可再插入!"<<endl;
	}
	m_poCN[i]=&oCN;//重载运算符
	cout<<"插入原有的结点,Pos:"<<m_aIndex<<",No:"<<oCN.GetNodeNum()<<",Name:"<<*oCN.GetStr()<<endl;
}
//这里不是链表操作,相当于delete一个结点,并让指针为空即可
bool CNodeArray::Delete(int index)
{
	if(m_poCN[index]==NULL)
	{
		cout<<"Pos:"<<index<<"=NULL,无需调用delete运算符."<<endl;
		return false;
	}
	delete m_poCN[index];//先释放当前结点应为结点可能指向某一块区域,先把它释放掉再将结点指向空NULL,m_poCN[i]是CNode类型,所以销毁它会自动运行析构函数~CNode()
	m_poCN[index]=NULL;
	cout<<"delete:m_poCN["<<index<<"],"<<"Pos:"<<index<<",次位置指向的结点delete成功!"<<endl;
	return true;
}
CNode CNodeArray::operator [](int i)
{
	if(i<m_aIndex&&(i>=0))
	{
		return *m_poCN[i];
	}
	else
	{
		if(m_poCN[i]==NULL)
		{
			cout<<"没有元素,出错."<<endl;
			exit(0);
		}
		cout<<"数组越界"<<endl;
		exit(0);
	}
}
void *CNodeArray::operator new(size_t size)
{
	cout<<"调用CNodeArray自定义的new创建对象.\n"<<endl;
	return malloc(size);//c++在以下三种情况下需要调用拷贝构造函数,当以对象作为函数参数,以值传递的方式传入函数体时;当以对象作为函数返回值,以值传递的方式从函数返回对象时;当用对象初始化另外一个对象时。
}//return 是以值传递所以创建了一个拷贝构造函数
void CNodeArray::operator delete(void *p)//上面已创建后而得到它的地址后就马上析构
{
	cout<<"调用CNodeArray自定义的delete销毁对象.\n";
	free(p);
}

sclass_cnode.h


#ifndef _SCLASS4_11_NODE_H_
#define _SCLASS4_11_NODE_H_

#include <iostream>
#include <string>//使用string类型就要用到string类型
using namespace std;

const int LEN=20;
class CNodeArray;//向前声明结点类数组类,以便在CNode类中声明为友元类使用

class CNode
{

	friend CNodeArray;
	friend ostream& operator<<(ostream& scout,CNode& obj);
	friend istream& operator>>(istream& scin,CNode& obj);
public:
	static int sNodeNum;
public:
	CNode(string str);//结点编号通过调用CreatNumber()函数得到
	CNode(const CNode &oCN);
	virtual ~CNode();
	CNode &operator=(const CNode &oCN);
	const CNode &operator,(const CNode &oCN);
	int GetNumber(void);
	string *GetStr();
	int &GetNodeNum();
private:
	string *m_pStr;
	int m_nodeNum;
};

class CNodeArray
{
	friend CNode;
public:
	CNodeArray(int aLength=LEN);
	virtual ~CNodeArray(void);
	CNode operator[](int i);
	void *operator new(size_t size);//size_t是vc中定义的一个类型而不是c++中定义的标准类型
	void operator delete(void *p);
	bool Insert(CNode &oCN);//在结点中插入一个结点
	void Insert(CNode &oCN,int i);
	bool Delete(int index);//在结点中删除一个结点
	int GetaIndex()
	{
		return m_aIndex;
	}
	CNode* operator()(int i)
	{
		return m_poCN[i];
	}
	void Revise(CNode &obc,int i)
	{
		m_poCN[i]=NULL;
		m_poCN[i]=&obc;
	}
private:
	CNode *m_poCN[LEN];//结点指针数组用来存放指向结点的指针
	int m_aLength;//指针数组长度
	int m_aIndex;//结点指针数组中数组的当前下标值
};

#endif


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值