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

来源:互联网 发布:新手学炒股 知乎 编辑:程序博客网 时间:2024/05/16 06:30
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;//当前结点下标设置为0cout<<"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
原创粉丝点击