12306高铁查询系统---设计报告

xiaoxiao2021-02-28  44

一,设计目标:

 

1.1.1对于管理员:

1>管理列车和站点的基本信息,包括增,删,查,改;

2>时间调度管理,对一特定车次增,删,查,改某一指定站点的列车行车信息。

1.1.2对于用户:

1>按出发站和到达站两站点查询列车;

2>按出发站和到达站两站点及出发时间查询列车;

3>按出发站和到达站两站点及到达时间查询列车;

具体要求:

1.2.1建立2个数据文件(站点station.txt、车次train.txt);

1.2.2要有3个数据类:

1>列车信息Information(含车次train_number、站点station、到达时间t1、开车时间t2,时间表示为时、分);

2>站点Station(含站点名称name、经过的车次向量(元素为列车信息);

      3>车次train_number(含车次编号number、始发站、终点站、经过的站点向量(元素为列车信息));

1.2.3 要有2个操作类:

            1>后台管理类AdminOp

            数据成员:站点向量、车次向量;                 

实现功能:站点基本信息管理、车次基本信息管理、查询车次/站点信息、时间调度管理(按车次安排站点时间、修改站点时间、删除/增加站点,对应的站点对象的信息也要做相应的改变)

2>客户操作类ClientOp

            数据成员:站点向量、车次向量;

            实现功能:   

            站点信息查询:查询指定站点所经过的车次信息;

            车次信息查询:查询指定车次所经过的站点信息;

      基本查询:(输入起始、目的地站,查看相关的车次信息)依次从起始站点取出经过该站的车次,到目的地站对象中查找相应的车次信息,找到即显示。继续直到起始站所有车次处理完;

带时间限定的查询:分为起始站发车时间限定查询和目的地到达时间限定查询

      中间换乘查询(选做):对于不能直接到达的基本查询,选取一个中间站点找到两个接力的车次以完成旅行。

1.2.4测试要求:

用3个不同的操作类对象运行管理端程序(与客户端程序间隔运行),完成对车次、站点信息的增删查改操作、时间调度管理。在数据文件中要有所反映;

      分别定义3个客户端对象,在运行完管理端操作后运行各种查询。

二,功能概要

      2.1.1对于管理员AdminOp:

1>管理员操作类AdminOp操作对象是车次集合cars与站点集合stops,其功能包括对车次集合Cars与站点集合Stops中的任意一辆车或者站点的增,删,查,改;不可忽视的是车次和站点之间的联系。

2.1.2对于用户操作类ClientOp

1>用户操作类ClientOp操作对象也是车次集合cars与站点集合stops,其功能只有查询,各种查询,不改变数据。

2,规划思路

      2.2.1梳理类之间的数据关系

            1>管理员操作类AdminOp和用户操作类ClientOp

管理员操作类AdminOp和用户操作类ClientOp是两个操作类,它们的操作对象,也就是数据成员是相同的,车次集合Cars, 站点集合Stops,即可以让管理员AdminOp和用户ClientOp继承车次集合Cars和站点集合Stops

            2>车次集合Cars和站点集合Stops

      车次集合Cars和站点集合Stops是两个相对独立又相联系的集合类,可以将其组合在一起,形成一个车次站点集合类CarsAStops,

            3>车次站点集合类CarsAStops

      车次站点集合类CarsAStops包含车次类OneCar和站点类Stop,即两个向量中的元素分别为车次类OneCar和站点类Stop;对于车次类Onecar而言,包括车次的基本信息和列车信息集合类CarInfos;对于站点类Stop而言,包括站点的基本信息和列车信息集合类CarInfos;由此可以看出,车次类OneCar和站点类Stop有共同的的数据成员:列车信息集合类CarInfos,则可以将其拿出单独成类,让车次类OneCar和站点类Stop都继承它。

            4>列车信息集合类CarInfos

            列车信息集合类CarInfos为元素列车信息类CarInfo的向量,该元素即包括某车次在在某站的基本信息以及停靠和发车时间,包含一个时间类Time;

            5>时间类Time

            只包含时hour和分minute两个基本数据成员

      2.2.2梳理类之间的功能关系

            1>管理员操作类AdminOp和用户操作类ClientOp

管理员操作类AdminOp和用户操作类ClientOp要实现的功能有相同的也有不同的,相同的功能包含在列车信息集合类CarsAStops里,两者直接继承即可,不同功能在自身类内实现。

两者相同的功能有:

其一:按车名,车次查找,得到所有的车次或者站点信息,都在列车信息集合类CarsAStops里直接实现;

其二:从数据文件里面读取站点和车次数据、将数据信息保存到文件里,因为管理员操作类AdminOp和用户操作类ClientOp的操作对象不仅仅是类型一样,内容也是统一的,即他们操作的数据文件也是相同的,则可将从文件读入数据,将数据输出到文件也写入列车信息集合类CarsAStops,对CarsAStops操作,也就是对车次集合Cars和站点集合Stops的直接操作。

两者不同的功能:

其一:对于管理员操作类AdminOp而言,更重要的是信息的维护工作。首先,是一条线路的从无到有,要对Cars和Stops进行基本信息的输入,之后再对之前加入的车次Car逐一进行增加停靠站点和停靠时间,与此同时对其中涉及的站点Stop也添加相应的记录;其次,对指定车次Car进行增加,删除,修改停靠站点操作,则对应的站点Stop作相应的改变,则需要对站点Stop进行增加、删除或者查找、修改时间的操作。

其二:对用户操作类ClientOp而言,除了基本的查询,更多的是需要相对精准的查询。包括按起始站和终点站的查询、按起始站和终点站以及有发车时间限制的查询、按起始站和终点站以及有终点到达时间限制的查询,则需要对大量的车站Stops和车次Cars进行更加精准快速的查询。

            2>车次集合Cars和站点集合Stops

      两个集合功能十分相似,且前面解释了将车次集合Cars和站点集合Stops合并为一个类进行操作,其功能则在合并后的车次站点集合类CarsAStops实现。

            3>车次站点集合类CarsAStops

      车次站点集合类CarsAStops包含以车次类OneCar和站点类Stop为元素的两向量,两向量实现功能与,两者具有相同的功能,则只详细阐述车次类Car的功能及与其他类的关系。

当对管理员提供修改某车次某站点的信息时、对用户提供更加精准的查询时,都需要对列车信息集合类CarInfos中的信息进行筛选比较;用户查询到后还要将该车基本信息以及两站起止时间直观的输出到屏幕上。

            4>列车信息集合类CarInfos

      当指定某车或者某站点时,其余的就是对该车或者该站点进行列车信息CarInfos进行查找,修改,和输出操作,可修改的数据成员包括到站时间和发车时间两个时间类Time对象。

            5>时间类Time

            只包含时hour和分minute两个基本数据成员

三,实现代码

#include<bits/stdc++.h> using namespace std; class Time{ int hour, minute; public: Time(int a=-1,int b=-1):hour(a),minute(b){} Time(const Time &obj){ hour=obj.hour; minute=obj.minute; } int getHour(){return hour;} int getMinute(){return minute;} Time getTime(){return *this;} void set(int a,int b){ hour=a; minute=b; } bool operator<(const Time&t1)const{ return hour!=t1.hour ? hour<t1.hour : minute<t1.minute; } bool operator==(const Time &t1)const{ if(hour==t1.hour&&minute==t1.minute) return true; else return false; } friend istream&operator>>(istream &is,Time&t){ is>>t.hour; is>>t.minute; return is; } friend ostream&operator<<(ostream &os,const Time&t){ os<<t.hour<<" "; os<<t.minute<<" "; return os; } }; class CarInfo{ string carName; string stopName; Time cameTime; Time goTime; public: CarInfo(){ carName="AAA"; //cameTime.set(-1,-1);goTime.set(-1,-1);无参数时Time类默认构造成-1 stopName="中国"; } CarInfo(string cName,string sName,Time t1,Time t2){ carName=cName; stopName=sName; cameTime=t1; goTime=t2; } CarInfo(string cName,string sName,int a,int b,int c,int d):carName(cName),stopName(sName),cameTime(a,b),goTime(c,d){} string getCarName(){return carName;} string getStopName(){return stopName;} Time getCameTime(){return cameTime;} Time getGoTime(){return goTime;} CarInfo getCar_record(){return *this;} void setCarName(string s){carName=s;} void setStopName(string s){stopName=s;} void setCameTime(Time t1){cameTime=t1;} void setCameTime(int a,int b){cameTime.set(a,b);} void setGoTime(Time t2){goTime=t2;} void setGoTime(int a,int b){goTime.set(a,b);} void set(string cName,string sName,Time t1,Time t2){ carName=cName; stopName=sName; cameTime=t1; goTime=t2; } void set(string cName,string sName,int a,int b,int c,int d){ carName=cName; stopName=sName; cameTime.set(a,b); goTime.set(c,d); } bool operator ==(const CarInfo &c_r1)const{ if(cameTime==c_r1.cameTime) return true; else return false; } friend istream &operator >>(istream &is,CarInfo &obj){ is>>obj.carName; is>>obj.stopName; is>>obj.cameTime; is>>obj.goTime; return is; } friend ostream &operator<<(ostream &os,const CarInfo &obj){ os<<obj.carName<<"\t"; os<<obj.stopName<<"\t"; os<<obj.cameTime<<"\t"; os<<obj.goTime<<endl; return os; } }; class CarInfos{ protected: int rNum; vector<CarInfo> record; vector<CarInfo>::iterator p_cr1,p_cr2; //在stop中使用 multimap<string,int> m_carName;//按车次查询该元素所在位置 multimap<string,int>::iterator pm_cN1,pm_cN2; //只在车次中使用 multimap<string,int> m_stopName;//按站点查询该元素所在位置 multimap<string,int>::iterator pm_sN1,pm_sN2; multimap<Time,int> m_cameTime;//按到达时间查询该元素所在位置 multimap<Time,int>::iterator pm_cT1,pm_cT2; public: CarInfos(){rNum=0;} int getRNum(){return rNum;} Time getCameTime(string carN){ pm_cN1=m_carName.find(carN); return record[pm_cN1->second].getCameTime(); } Time getGoTime(string carN){ pm_cN1=m_carName.find(carN); return record[pm_cN1->second].getGoTime(); } void getRecords(){//美观的输出记录用的; p_cr1=record.begin(); p_cr2=record.end(); int x=0; for(p_cr1;p_cr1!=p_cr2;p_cr1++){ cout<<" 记录编号:"<<++x ; cout<<" 列车名:"<<p_cr1->getCarName()<<" 车站名为:"<<p_cr1->getStopName() <<" 到达时间:"<<p_cr1->getCameTime()<<" 发车时间:"<<p_cr1->getGoTime()<<endl; } } vector<CarInfo> getRecord(){return record;} friend istream &operator >>(istream &is,CarInfos &obj){ is>>obj.rNum; for(int i=1;i<=obj.rNum;i++){ CarInfo car1; is>>car1; obj.record.push_back(car1); obj.m_carName.insert(make_pair(car1.getCarName(),i-1)); obj.m_stopName.insert(make_pair(car1.getStopName(),i-1)); obj.m_cameTime.insert(make_pair(car1.getCameTime(),i-1)); } return is; } friend ostream &operator <<(ostream &os,CarInfos &obj){ //集合的输出应该用指针遍历,而不能按个数for循环,否则,只只遍历了前面几个,因为删除操作是隐藏而非真正的删除 os<<obj.rNum<<endl; obj.p_cr1=obj.record.begin(); obj.p_cr2=obj.record.end(); for(obj.p_cr1;obj.p_cr1!=obj.p_cr2;obj.p_cr1++){ os<<*obj.p_cr1<<endl; } return os; } void addOneRecord(string cName,string sName,int a,int b,int c,int d){ CarInfo car1(cName,sName,a,b,c,d); record.push_back(car1); m_carName.insert(make_pair(cName,rNum)); m_stopName.insert(make_pair(sName,rNum)); Time t1(a,b),t2(c,d); m_cameTime.insert(make_pair(t1,rNum)); rNum++; } void addOneRecord(string cName,string sName,Time t1,Time t2){ CarInfo car1(cName,sName,t1,t2); record.push_back(car1); m_carName.insert(make_pair(cName,rNum)); m_stopName.insert(make_pair(sName,rNum)); m_cameTime.insert(make_pair(t1,rNum)); rNum++; } }; class OneCar:public CarInfos{//这个重载运算符里面没有自动往地图里面加东西,很绝望,果然,今天写下的代码都是明天的bug string carName, startSite, endSite; public: OneCar(){ rNum=0; carName="AAA"; startSite="中国"; endSite="中国"; } OneCar(string cN,string ss,string es){ rNum=0; carName=cN; startSite=ss; endSite=es; } string getCarName(){return carName;} string getStartSite(){return startSite;} string getEndSite(){return endSite;} void setCarName(string s){carName=s;} void setStartSite(string s){startSite=s;} void setEndSite(string s){endSite=s;} void set(string cN,string ss,string es){ carName=cN; startSite=ss; endSite=es; } friend istream &operator >>(istream &is,OneCar &obj){ is>>obj.carName; is>>obj.startSite; is>>obj.endSite; is>>obj.rNum; obj.record.clear(); obj.m_carName.clear(); obj.m_stopName.clear(); obj.m_cameTime.clear(); for(int i=1;i<=obj.rNum;i++){ CarInfo car1; is>>car1; obj.record.push_back(car1); obj.m_carName.insert(make_pair(car1.getCarName(),i-1)); obj.m_stopName.insert(make_pair(car1.getStopName(),i-1)); obj.m_cameTime.insert(make_pair(car1.getCameTime(),i-1)); } return is; } friend ostream &operator <<(ostream &os,OneCar &obj){ os<<obj.carName<<" "; os<<obj.startSite<<" "; os<<obj.endSite<<" "; os<<obj.rNum<<endl; obj.p_cr1=obj.record.begin(); obj.p_cr2=obj.record.end(); for(obj.p_cr1;obj.p_cr1!=obj.p_cr2;obj.p_cr1++){ os<<*obj.p_cr1<<endl; } return os; } bool have_Stop(string sName){ int a=m_stopName.count(sName); if(a>0) return 1; else return 0; } void qByStopName(string sName){ pm_sN1=m_stopName.find(sName); if(pm_sN1!=m_stopName.end()) cout<<record[pm_sN1->second]<<endl; } //时间调度管理,在后台管理类调用时,记得同时更改所提及的站点对象的对应车次 void changeOneStop(string sName,Time t1,Time t2){//注意更改的时间不能与其他站点的时间相同,否则按时间的指针将有多义性 pm_sN1=m_stopName.find(sName); if(pm_sN1!=m_stopName.end()){ pm_cT1=m_cameTime.find(record[pm_sN1->second].getCameTime()); int a=pm_cT1->second; m_cameTime.erase(pm_cT1); m_cameTime.insert(make_pair(t1,a));//还是原来的位置,只是那个位置的时间变了 record[pm_sN1->second].setCameTime(t1); record[pm_sN1->second].setGoTime(t2); } } void delRecoByStop(string sName){ pm_sN1=m_stopName.find(sName);//在map_stopName中按stopName查找 int a=pm_sN1->second;//a=该元素在record中的位置下标; m_stopName.erase(pm_sN1);//map_StopName的此位置的元素删去 pm_sN1=m_stopName.begin(); pm_sN2=m_stopName.end(); for(pm_sN1;pm_sN1!=pm_sN2;pm_sN1++){//遍历map_carName中剩余得列车信息,所有的,原来在vector中位置大于被删元素的,元素在vector的中的位置都向前一位 if(pm_sN1->second>a){ pm_sN1->second--; break;//按车次名删除,对一个站点来说,不存在重复的情况 } } pm_cT1=m_cameTime.find(record[a].getCameTime());//在map_cameTime中按该元素的cameTime查找 m_cameTime.erase(pm_cT1);//map_carName的此位置的元素删去 pm_cT1=m_cameTime.begin(); pm_cT2=m_cameTime.end(); for(pm_cT1;pm_cT1!=pm_cT2;pm_cT1++){//遍历map_carName中剩余得列车信息,所有的,原来在vector中位置大于被删元素的,元素在vector的中的位置都向前一位 if(pm_cT1->second>a){ pm_cT1->second--; break;//按车次名删除,对一个站点来说,不存在重复的情况 } } p_cr1=record.begin();删除vector中的记录 p_cr2=record.end(); for(p_cr1;p_cr1!=p_cr2;p_cr1++){//遍历vector if(p_cr1->getStopName()==sName){//找到cName所属的列车信息 p_cr1=record.erase(p_cr1);//删除vector中的记录 break;//按车次名删除,对一个站点来说,不存在重复的情况 } } rNum--; } void addOneStop(string sName,Time t1,Time t2){ CarInfo car1(carName,sName,t1,t2); record.push_back(car1); m_stopName.insert(make_pair(sName,rNum)); m_cameTime.insert(make_pair(t1,rNum)); rNum++; } }; class Stop:public CarInfos{ string stopName; public: Stop(){ stopName="中国"; rNum=0; } Stop(string name){ stopName=name; rNum=0; } string getStopName(){return stopName;} void setStopName(string s){stopName=s;} friend istream &operator >>(istream &is,Stop &obj){ is>>obj.stopName; is>>obj.rNum; obj.record.clear();//这个和OneCar类里面加记录时都没清空,也是,差点把我玩死 obj.m_carName.clear(); obj.m_stopName.clear(); obj.m_cameTime.clear(); for(int i=1;i<=obj.rNum;i++) { CarInfo car1; is>>car1; obj.record.push_back(car1); obj.m_carName.insert(make_pair(car1.getCarName(),i-1)); obj.m_stopName.insert(make_pair(car1.getStopName(),i-1)); obj.m_cameTime.insert(make_pair(car1.getCameTime(),i-1)); } return is; } friend ostream &operator <<(ostream &os,Stop &obj){//问题:怎样在子类中调用父类的 << ?? os<<obj.stopName<<" "; os<<obj.rNum<<endl; obj.p_cr1=obj.record.begin(); obj.p_cr2=obj.record.end(); for(obj.p_cr1;obj.p_cr1!=obj.p_cr2;obj.p_cr1++){ os<<*obj.p_cr1<<endl; } return os; } bool have_Car(string cName){//查询有没有 int a=m_carName.count(cName); if(a>0) return 1; else return 0; } void qByCarName(string cName){//确定有后将其输出 pm_cN1=m_carName.find(cName); if(pm_cN1!=m_carName.end()) cout<<record[pm_cN1->second]<<endl; } void changeOneCar(string cName,Time t1,Time t2){//注意更改的时间不能与其他站点的时间相同,否则按时间的指针将有多义性 pm_cN1=m_carName.find(cName); if(pm_cN1!=m_carName.end()){ pm_cT1=m_cameTime.find(record[pm_cN1->second].getCameTime()); int a=pm_cT1->second; m_cameTime.erase(pm_cT1); m_cameTime.insert(make_pair(t1,a));//还是原来的位置,只是那个位置的时间变了 record[pm_cN1->second].setCameTime(t1); record[pm_cN1->second].setGoTime(t2); } } void delRecoByCar(string cName){//在vector,map中将其删去, pm_cN1=m_carName.find(cName); //在map_carName中按carName查找,找到该元素; int a=pm_cN1->second;//a=该元素在record中的位置下标; m_carName.erase(pm_cN1); //map_carName的此位置的元素删去 pm_cN1=m_carName.begin(); pm_cN2=m_carName.end(); for(pm_cN1;pm_cN1!=pm_cN2;pm_cN1++){//遍历map_carName中剩余得列车信息,所有的,原来在vector中位置大于被删元素的,元素在vector的中的位置都向前一位 if(pm_cN1->second>a){ pm_cN1->second--; break;//按车次名删除,对一个站点来说,不存在重复的情况 } } pm_cT1=m_cameTime.find(record[a].getCameTime()); //在map_cameTime中按该元素的cameTime查找 m_cameTime.erase(pm_cT1);//map_carName的此位置的元素删去 pm_cT1=m_cameTime.begin(); pm_cT2=m_cameTime.end(); for(pm_cT1;pm_cT1!=pm_cT2;pm_cT1++){//遍历map_carName中剩余得列车信息,所有的,原来在vector中位置大于被删元素的,元素在vector的中的位置都向前一位 if(pm_cT1->second>a){ pm_cT1->second--; break; } } p_cr1=record.begin();删除vector中的记录 p_cr2=record.end(); for(p_cr1;p_cr1!=p_cr2;p_cr1++){//遍历vector if(p_cr1->getCarName()==cName){//找到cName所属的列车信息 p_cr1=record.erase(p_cr1);//删除vector中的记录 break; } } rNum--; } void addOneCar(string cName,Time t1,Time t2){ CarInfo car1(cName,stopName,t1,t2); record.push_back(car1); m_carName.insert(make_pair(cName,rNum)); m_cameTime.insert(make_pair(t1,rNum)); rNum++; } }; class CarsAStops{ protected: int carNum; int stopNum; vector<OneCar> cars; vector<OneCar>::iterator pv_c1,pv_c2; multimap<string,int> m_cName; multimap<string,int>::iterator pm_cN1,pm_cN2; vector<Stop> stops; vector<Stop>::iterator pv_s1,pv_s2; multimap<string,int> m_sName; multimap<string,int>::iterator pm_sN1,pm_sN2; public: void loadCar(){//我的个亲娘嘞,x在里面就一直是0,这能把我玩死 ifstream infile("train.txt",ios::in); if(!infile) return ; cars.clear(); m_cName.clear(); OneCar c1; int x=0; while(infile>>c1){ cars.push_back(c1); carNum++; m_cName.insert(make_pair(c1.getCarName(),x++)); }; } void saveCar(){ ofstream outfile("train.txt",ios::out); if(!outfile) return; for(pv_c1=cars.begin();pv_c1!=cars.end();pv_c1++){ outfile<<*pv_c1; } outfile.close(); } void loadStop(){ ifstream infile("station.txt",ios::in); if(!infile) return ; stops.clear(); m_sName.clear(); Stop s1; int x=0; while(infile>>s1){ stops.push_back(s1); stopNum++; m_sName.insert(make_pair(s1.getStopName(),x++)); }; } void saveStop(){ ofstream outfile("station.txt",ios::out); if(!outfile) return; for(pv_s1=stops.begin();pv_s1!=stops.end();pv_s1++){ outfile<<*pv_s1; } outfile.close(); } CarsAStops(){ carNum=0; stopNum=0; loadCar(); loadStop(); } ~CarsAStops() { saveCar(); saveStop(); } int getCarNum(){return carNum;} int getStopNum(){return stopNum;} void addCar(string cN,string ss,string es){ OneCar car1(cN,ss,es); cars.push_back(car1); m_cName.insert(make_pair(cN,carNum)); carNum++; } void deleCar(string cN){//车站里面对应这个车次的记录都删掉 pm_cN1=m_cName.find(cN); int a=pm_cN1->second; m_cName.erase(pm_cN1);//在map_carName中将其删除 pm_cN1=m_cName.begin(); pm_cN2=m_cName.end(); for(pm_cN1;pm_cN1!=pm_cN2;pm_cN1++){//在vector中在该删除元素之后的其他元素,都往前顺延了一个位置 if(pm_cN1->second>a) pm_cN1->second--; } pm_sN1=m_sName.begin(); pm_sN2=m_sName.end(); for(pm_sN1;pm_sN1!=pm_sN2;pm_sN1++){ if(stops[pm_sN1->second].have_Car(cN)==1){//如果有这个站点有这量车的信息,删除 stops[pm_sN1->second].delRecoByCar(cN); } } pv_c1=cars.begin();//最后再从列车向量里将其整个删除,前面会用到里面的内容 pv_c2=cars.end(); for(pv_c1;pv_c1!=pv_c2;pv_c1++){ if(pv_c1->getCarName()==cN){ cars.erase(pv_c1); } } carNum--; } void addStop(string sN){ Stop stop1(sN); stops.push_back(stop1); m_sName.insert(make_pair(sN,stopNum)); stopNum++; } void deleStop(string sN){//车次里面对应这个车站的记录都删掉 pm_sN1=m_sName.find(sN); int a=pm_sN1->second; m_sName.erase(pm_sN1);//在map_carName中将其删除 pm_sN1=m_sName.begin(); pm_sN2=m_sName.end(); for(pm_sN1;pm_sN1!=pm_sN2;pm_sN1++){//在vector中在该删除元素之后的其他元素,都往前顺延了一个位置 if(pm_sN1->second>a) pm_sN1->second--; } pm_cN1=m_cName.begin(); pm_cN2=m_cName.end(); for(pm_cN1;pm_cN1!=pm_cN2;pm_cN1++){ if(cars[pm_cN1->second].have_Stop(sN)==1){//如果这量车有这个站点有的信息,删除 cars[pm_cN1->second].delRecoByStop(sN); } } pv_s1=stops.begin();//最后再从战点向量里将其整个删除,前面会用到里面的内容 pv_s2=stops.end(); for(pv_s1;pv_s1!=pv_s2;pv_s1++){ if(pv_s1->getStopName()==sN){ stops.erase(pv_s1); } } stopNum--; } void addCarRecord(string cName,string sName,Time t1,Time t2){//给一辆已经存在的车添加记录,对应的站点也加上该车次 pm_cN1=m_cName.find(cName);//找到该车 int a=pm_cN1->second; cars[a].addOneStop(sName,t1,t2); pm_sN1=m_sName.find(sName);//在站点集合里找到该站点 int b=pm_sN1->second; stops[b].addOneCar(cName,t1,t2); } void addCarRecord(string cName,string sName,int a1,int b1,int c,int d){//给一辆已经存在的车添加记录,对应的站点也加上该车次 pm_cN1=m_cName.find(cName);//找到该车 int a=pm_cN1->second; Time t1(a1,b1),t2(c,d); cars[a].addOneStop(sName,t1,t2); pm_sN1=m_sName.find(sName);//在站点集合里找到该站点 int b=pm_sN1->second; stops[b].addOneCar(cName,t1,t2); } void deleCarRecord(string cName,string sName){//对哪个车cName的哪个站点sName,进行删除操作 pm_cN1=m_cName.find(cName);//找到该车 int a=pm_cN1->second; cars[a].delRecoByStop(sName); pm_sN1=m_sName.find(sName);//在站点集合里找到该站点 int b=pm_sN1->second; stops[b].delRecoByCar(cName); } void gaiCarRecordTime(string cName,string sName,Time t1,Time t2){ pm_cN1=m_cName.find(cName);//找到该车 int a=pm_cN1->second; cars[a].changeOneStop(sName,t1,t2); pm_sN1=m_sName.find(sName);//在站点集合里找到该站点 int b=pm_sN1->second; stops[b].changeOneCar(cName,t1,t2);// } void gaiCarRecordTime(string cName,string sName,int a1,int b1,int c,int d){ pm_cN1=m_cName.find(cName);//找到该车 int a=pm_cN1->second; Time t1(a1,b1),t2(c,d); cars[a].changeOneStop(sName,t1,t2); pm_sN1=m_sName.find(sName);//在站点集合里找到该站点 int b=pm_sN1->second; stops[b].changeOneCar(cName,t1,t2);// } void qByOneCar(){ string c1; cout<<"请输入您想查询的车次:"<<endl; cin>>c1 ; q_OneCar(c1); } void getAllCar(){ cout<<"列车共有"<<carNum<<"辆:"<<endl; int x=0; pv_c1=cars.begin(); pv_c2=cars.end(); for(pv_c1;pv_c1!=pv_c2;pv_c1++){ cout<<"站点编号:"<<++x<<" 车次:"<<pv_c1->getCarName() <<" 始发站:"<<pv_c1->getStartSite()<<" 终点站:"<<pv_c1->getEndSite()<<endl; } } void getAllAllCar(){ cout<<"列车共有"<<carNum<<"辆:"<<endl; int x=0; pv_c1=cars.begin(); pv_c2=cars.end(); for(pv_c1;pv_c1!=pv_c2;pv_c1++){ cout<<"列车编号:"<<++x<<" 车次:"<<pv_c1->getCarName() <<" 始发站:"<<pv_c1->getStartSite()<<" 终点站:"<<pv_c1->getEndSite()<<endl; cout<<" 内部记录有"<<pv_c1->getRNum()<<"条"<<endl; if(pv_c1->getRNum()>0){ pv_c1->getRecords(); } } } void getAllStop(){ cout<<"站点共有"<<stopNum<<"个:"<<endl; int x=0; pv_s1=stops.begin(); pv_s2=stops.end(); for(pv_s1;pv_s1!=pv_s2;pv_s1++){ cout<<"站点编号:"<<++x<<" 站名:"<<pv_s1->getStopName()<<endl; } } void getAllAllStop(){ cout<<"站点共有"<<stopNum<<"个:"<<endl; int x=0; pv_s1=stops.begin(); pv_s2=stops.end(); for(pv_s1;pv_s1!=pv_s2;pv_s1++){ cout<<"站点编号:"<<++x<<" 站名:"<<pv_s1->getStopName()<<endl; cout<<" 内部记录有"<<pv_s1->getRNum()<<"条"<<endl; if(pv_s1->getRNum()>0){ pv_s1->getRecords(); } } } void q_OneCar(string carN){ pm_cN1=m_cName.find(carN); pm_cN2=m_cName.end(); if(pm_cN1!=pm_cN2){ cout<<"查询到车次为\""<<carN<<"\"的列车,列车信息如下:"<<endl; cout<<cars[pm_cN1->second]<<endl; } else cout<<"您查询的\""<<carN<<"\"列车不存在"<<endl; } void q_OneStop(string stopN){ pm_sN1=m_sName.find(stopN); pm_sN2=m_sName.end(); if(pm_sN1!=pm_sN2){ cout<<"查询到站名为\""<<stopN<<"\"的站点,站点信息如下:"<<endl; cout<<stops[pm_sN1->second]<<endl; } else cout<<"您查询的\""<<stopN<<"\"站点不存在"<<endl; } /*void huan_TwoStop(string s1,string s2){ pm_sN1=m_sName.find(s1); pm_sN2=m_sName.find(s2);//地图中找到对应开始车站 int a=pm_sN1->second; int b=pm_sN2->second;//对应到vector中两车站下标; vector<CarInfo> stop1; vector<CarInfo>::iterator pss1,pss2; stop1=stops[a].getRecord();//将第一个车站里的向量拿出来 pss1=stop1.begin(); pss2=stop1.end();//遍历起始地点的发车车次 int flag=0; }*/ void q_ByTwoStop(string s1,string s2){ pm_sN1=m_sName.find(s1); pm_sN2=m_sName.find(s2);//地图中找到对应车站 int a=pm_sN1->second; int b=pm_sN2->second;//对应到vector中两车站下标; vector<CarInfo> stop1,stop2; vector<CarInfo>::iterator pss1,pss2; stop1=stops[a].getRecord();//将第一个车站里的向量拿出来 pss1=stop1.begin(); pss2=stop1.end();//遍历起始地点的发车车次 int flag=0; for(pss1;pss1!=pss2;pss1++){//遍历一个站点里的车次,另一个查找 //if((t1<pss1->getGoTime()||t1==pss1->getGoTime())&&(pss1->getGoTime()<t2||pss1->getGoTime()==t2)){ if(stops[b].have_Car(pss1->getCarName())){ if(flag==0){ cout<<"查询到从"<<s1<<"到"<<s2<<"的车次,车次的信息为:"<<endl; flag=1; } OneCar ca1;//为了得到该车次的始发站和终点站 pm_cN1=m_cName.find(pss1->getCarName()); ca1=cars[pm_cN1->second]; cout<<"车次:"<<pss1->getCarName()<<" 始发站:"<<ca1.getStartSite() <<" 终点站:"<<ca1.getEndSite()<<endl; cout<<"在"<<s1<<"站的发车时间:"<<pss1->getGoTime() <<"\n到达"<<s2<<"站的时间:"<<stops[b].getCameTime(pss1->getCarName())<<endl<<endl; } } // } if(flag==0){ cout<<"没有找到符合您查询要求的列车!"<<endl; } } void q_ByStopAndGoTime(string s1,string s2,Time t1,Time t2){ pm_sN1=m_sName.find(s1); pm_sN2=m_sName.find(s2);//地图中找到对应车站 int a=pm_sN1->second; int b=pm_sN2->second;//对应到vector中两车站下标; vector<CarInfo> stop1,stop2; vector<CarInfo>::iterator pss1,pss2; stop1=stops[a].getRecord();//将第一个车站里的向量拿出来 pss1=stop1.begin(); pss2=stop1.end();//遍历起始地点的发车车次 int flag=0; for(pss1;pss1!=pss2;pss1++){//遍历一个站点里的车次,另一个查找 Time tt; tt=pss1->getGoTime(); if((t1<tt||t1==tt)&&(tt<t2||tt==t2)){ if(stops[b].have_Car(pss1->getCarName())){ if(flag==0){ cout<<"查询到发车时间在"<<t1<<"与"<<t2<<"之内\n从"<<s1<<"到"<<s2<<"的车次,车次的信息为:"<<endl; flag=1; } OneCar ca1;//为了得到该车次的始发站和终点站 pm_cN1=m_cName.find(pss1->getCarName()); ca1=cars[pm_cN1->second]; cout<<"车次:"<<pss1->getCarName()<<" 始发站:"<<ca1.getStartSite()<<" 终点站:"<<ca1.getEndSite()<<endl; cout<<"在"<<s1<<"站的发车时间:"<<pss1->getGoTime()<<"\n到达"<<s2<<"站的时间:"<<stops[b].getCameTime(pss1->getCarName())<<endl; cout<<endl; } } } if(flag==0)cout<<"没有找到符合您查询要求的列车!"<<endl; } void q_ByStopAndToTime(string s1,string s2,Time t1,Time t2){ pm_sN1=m_sName.find(s1); pm_sN2=m_sName.find(s2);//地图中找到对应车站 int a=pm_sN1->second; int b=pm_sN2->second;//对应到vector中两车站下标; vector<CarInfo> stop1,stop2; vector<CarInfo>::iterator pss1,pss2; stop1=stops[a].getRecord();//将第一个车站里的向量拿出来 pss1=stop1.begin(); pss2=stop1.end();//遍历起始地点的发车车次 int flag=0; for(pss1;pss1!=pss2;pss1++){//遍历一个站点里的车次,另一个查找 Time tt; tt=stops[b].getCameTime(pss1->getCarName()); if((t1<tt||t1==tt)&&(tt<t2||tt==t2)){ if(stops[b].have_Car(pss1->getCarName())){ if(flag==0){ cout<<"查询到到达时间在"<<t1<<"与"<<t2<<"之内\n从"<<s1<<"到"<<s2<<"的车次,车次的信息为:"<<endl; flag=1; } OneCar ca1;//为了得到该车次的始发站和终点站 pm_cN1=m_cName.find(pss1->getCarName()); ca1=cars[pm_cN1->second]; cout<<"车次:"<<pss1->getCarName()<<" 始发站:"<<ca1.getStartSite()<<" 终点站:"<<ca1.getEndSite()<<endl; cout<<"在"<<s1<<"站的发车时间:"<<pss1->getGoTime()<<"\n到达"<<s2<<"站的时间:"<<stops[b].getCameTime(pss1->getCarName())<<endl; cout<<endl; } } } if(flag==0)cout<<"没有找到符合您查询要求的列车!"<<endl; } }; class AdminOp:public CarsAStops{ public: AdminOp(){ carNum=0; stopNum=0; } void A_addCar(){ string cN="GG",ss,es; cout<<"请输入您想添加的车次的车次名,始发站,和终点站(输入-1表示结束):"<<endl; while(1) { cin>>cN; if(cN=="-1"){ cout<<"车次添加完成!"<<endl; break; } cin>>ss>>es; addCar(cN,ss,es); } } void A_deleCar(){//车站里面对应这个车次的记录都删掉 string cN1; cout<<"请输入您想删除车次的车次名(输入-1表示结束):"<<endl; while(1) { cin>>cN1; if(cN1=="-1"){ cout<<"车次删除完成!"<<endl ; break; } deleCar(cN1); } } void A_addStop(){ string sN; cout<<"请输入您想添加的站点的站名:"<<endl; while(1) { cin>>sN; if(sN=="-1"){ cout<<"站点增加完成!"<<endl; break; } addStop(sN); } } void A_deleStop(){//车次里面对应这个车站的记录都删掉 string sN; cout<<"请输入您想删除的车站名:"<<endl; while(1) { cin>>sN; if(sN=="-1"){ cout<<"站点删除完成!"<<endl; break; } deleStop(sN); } } void A_addCarRecord(){//给一辆已经存在的车添加记录,对应的站点也加上该车次 string cName,sName; int a1,b1,c,d; cout<<"请输入您想加入记录的车次名称,以及记录的站点名称,在该站点的到站时间以及发车时间:"<<endl; while(1){ cin>>cName; if(cName=="-1") { cout<<"完成对某些车次的增加记录操作!"<<endl; break; } cin>>sName>>a1>>b1>>c>>d; addCarRecord(cName,sName,a1,b1,c,d); } } void A_deleCarRecord(){//对哪个车cName的哪个站点sName,进行删除操作 string cName,sName; cout<<"请输入您想删除记录的车次名称,以及记录的站点名称:"<<endl; while(1){ cin>>cName; if(cName=="-1") { cout<<"完成对某些车次的删除记录操作!"<<endl; break; } cin>>sName; deleCarRecord(cName,sName); } } void A_gaiCarRecordTime(){ string cName,sName; int a1,b1,c,d; cout<<"请输入您想修改记录的车次名称,以及记录的站点名称,在该站点的到站时间以及发车时间:"<<endl; while(1){ cin>>cName; if(cName=="-1") { cout<<"完成对某些车次的修改记录操作!"<<endl; break; } cin>>sName>>a1>>b1>>c>>d; gaiCarRecordTime(cName,sName,a1,b1,c,d); } } void handAdd(){ int a; cout<<"欢迎管理员登陆!"<<endl; cout<<"请问您本次是否添加一条线路的信息?(提示:如添加线路信息请输入1,不添加则输入-1,结束本次操作)\n请输入:"; cin>>a; if(a==1){ cout<<"请输入该线路所涉及的所有站点名称,输入-1表示结束:"<<endl; while(1){ string s; cin>>s; if(s=="-1"){ cout<<"站点加入完成!"<<endl; break; } else{ addStop(s); } } cout<<endl<<"请输入列车车次和及该车次的始发站和终点站,输入-1表示结束"<<endl; while(1){ string carN,starSite,endSite; cin>>carN; if(carN=="-1"){ cout<<"列车车次初始化完成!"<<endl; break; } else{ cin>>starSite>>endSite; addCar(carN,starSite,endSite); } } cout<<"您本次共加入了" <<carNum<<"辆车,请依次初始化这些车次的行车记录,全部完成后,方可结束本次操作:"<<endl; pv_c1=cars.begin(); pv_c2=cars.end(); for(pv_c1;pv_c1!=pv_c2;pv_c1++) { cout<<"请初始化车次为\""<<pv_c1->getCarName()<<"\"的列车行车记录,输入-1表示结束:"<<endl; cout<<"(提示:请依次输入该车次行车所到达的 站点名称,到站时间,以及出站时间)"<<endl; while(1){ string stopN; int a,b,c,d; cin>>stopN; if(stopN=="-1"){ cout<<"车次为"<<pv_c1->getCarName()<<"的列车行车记录初始化完成!"<<endl; break; } else{ cin>>a>>b>>c>>d; addCarRecord(pv_c1->getCarName(),stopN,a,b,c,d); } } } } else return; } }; class ClientOp:public CarsAStops{ public: void qOneCar(){ cout<<"请输入您想查询的车次:"<<endl; string caName; cin>>caName; q_OneCar(caName); } void qOneStop(){ string stName; cout<<"请输入您想查询的站点:"<<endl; cin>>stName; q_OneStop(stName); } void qByTwoStop(){ string stSite,enSite; cout<<"请输入您想查询的起点和终点:"<<endl; cin>>stSite>>enSite; q_ByTwoStop(stSite,enSite); } void qByStopAndGoTime(){ string stSite,enSite; int a,b,c,d; cout<<"请输入您想查询的起点,终点以及 起点发车时间范围:"<<endl; cin>>stSite>>enSite>>a>>b>>c>>d; Time t1(a,b),t2(c,d); q_ByStopAndGoTime(stSite,enSite,t1,t2); } void qByStopAndToTime(){ string stSite,enSite; int a,b,c,d; cout<<"请输入您想查询的起点,终点以及 终点到站时间范围:"<<endl; cin>>stSite>>enSite>>a>>b>>c>>d; Time t1(a,b),t2(c,d); q_ByStopAndToTime(stSite,enSite,t1,t2); } }; int main() { ClientOp cc3; //cc3.qOneCar();//用户查询-某一个特定的车次 //cc3.qOneStop();//用户查询-某一个特定的站点 //cc3.qByTwoStop();//用户查询-按两站点查询 //cc3.qByStopAndGoTime();//用户查询-按两站点+发车时间查询 cc3.qByStopAndToTime();//用户查询-按两站点+到站时间查询 return 0; } /* AdminOp ad3; ad3.A_addCarRecord();//时间调度管理-给一个车次增加一个停靠站点 //ad3.A_deleCarRecord();//时间调度管理-给一个车次删除一个停靠站点 //ad3.A_gaiCarRecordTime();//时间调度管理-给一个车次修改一个停靠站点 ClientOp cc2; //cc2.qOneCar();//用户查询-某一个特定的车次 //cc2.qOneStop();//用户查询-某一个特定的站点 //cc2.qByTwoStop();//用户查询-按两站点查询 cc2.qByStopAndGoTime();//用户查询-按两站点+发车时间查询 cc2.qByStopAndToTime();//用户查询-按两站点+到站时间查询 AdminOp ad2;//创建 ad2.A_addCar();//基本信息管理-添加一两车 ad2.A_deleCar();//基本信息管理-删除一整辆车 ad2.A_addStop();//基本信息管理-增加一个站点 ad2.A_deleStop();//基本信息管理-删除一整站点 ClientOp cc1; cc1.qOneCar();//用户查询-某一个特定的车次 cc1.qOneStop();//用户查询-某一个特定的站点 cc1.qByTwoStop();//用户查询-按两站点查询 cc1.qByStopAndGoTime();//用户查询-按两站点+发车时间查询 cc1.qByStopAndToTime();//用户查询-按两站点+到站时间查询*/ /* 用3个不同的操作类对象运行管理端程序(与客户端程序间隔运行), 完成对车次、站点信息的增删查改操作、时间调度管理。在数据文件中要有所反映; 分别定义3个客户端对象,在运行完管理端操作后运行各种查询。 ad1.A_addCar();//基本信息管理-添加一两车 ad1.A_deleCar();//基本信息管理-删除一整辆车 ad1.A_addStop();//基本信息管理-增加一个站点 ad1.A_deleStop();//基本信息管理-删除一整站点 ad1.getAllCar();//查询-只显示基本信息的查询(父类中的函数 ad1.getAllAllCar();//查询-显示详细信息的查询(父类中的函数 ad1.getAllStop();//查询-只显示基本信息的查询(父类中的函数 ad1.getAllAllStop();//查询-显示详细信息的查询(父类中的函数 ad1.A_addCarRecord();//时间调度管理-给一个车次增加一个停靠站点 ad1.A_deleCarRecord();//时间调度管理-给一个车次删除一个停靠站点 ad1.A_gaiCarRecordTime();//时间调度管理-给一个车次修改一个停靠站点 ClientOp cc1; cc1.qOneCar();//用户查询-某一个特定的车次 cc1.qOneStop();//用户查询-某一个特定的站点 cc1.qByTwoStop();//用户查询-按两站点查询 cc1.qByStopAndGoTime();//用户查询-按两站点+发车时间查询 cc1.qByStopAndToTime();//用户查询-按两站点+到站时间查询 */

 

五,遇到的问题

        5.1.1 向量删除操作与快速查找地图指向变换

当对一个向量中的元素进行删除操作时,该元素之后的元素的位置都发生了改变,指向该元素之后的的地图里的关键字,也就是对应元素的下标也就发生了改变。

最开始的解决办法是将被删除的元素的内容变成无效内容,这样就不用考虑位置变换,只需要在查询或者输出时加一个判断。

后来这么写着就觉得不是很正宗,而且这一个问题牵扯出来的查询,修改太多了,反而麻烦;于是就另寻方法:删除前先将该元素位置记录,然后遍历每一个map ,将value大于该位置的都减一,这样,只有这一个函数比较麻烦,而之后的功能实现就少了很多顾虑。

      5.1.2 将信息输出到屏幕上的格式要与输出到文件中的格式不同

            输入到文件中的信息光秃秃的,一开始屏幕上数据少的时候还能看懂,到了后来就越看越迷茫,还是应该有点提示信息的。

      5.1.3 输出向量中元素应按指针遍历输出,而不是for循环记录数目(基于删除功能是通过隐藏来实现的)

            这就是删除时隐藏信息的隐患之一,有效记录数目与实际记录数目不相同,在按个数从前向后读取时,信息输出不全。

      5.1.4 重载某些数据成员包含向量并且带有快速查询map的输入运算符时,没有自动向map里加数据。

            这就是我从文件中读入数据,然后怎么都查不到信息的原因。

      5.1.5 分不清时间调度管理中的功能与基本维护功能的关系

            经过老师的讲解现在还是比较明白的:对站点或者车次基本信息管理是指一整个车次,或者一整个站点;说的过分一点,增加一辆车就是新建一个火车,给它命上名,等待给它安排行车信息;删除就是将在用的车砸坏,不能用,该车所经过的所有的站点都失去了行车信息,站点类似的类似。时间调度管理是指在运行的车次,要对其中在某站点的停靠时间做修改,在站点中对应的额所涉及的站点也进行相应 的改变。

      5.1.6 重载某些数据成员包含向量并且带有快速查询map的输入运算符时,自动向map里加数据,但是,加入之前没将map清空

      这就是我即时在读取数据是自动加入了数据,但查询一直错误的原因。

      5.1.7 从文件读入数据信息的函数中,对map进行了自动添加数据,然而一开始预设的随加入对象数据数目而增大的变量一直没变

      即不管什么元素,这一类指针永远都指向位置0。

      5.1.8 算是个人程序设计思想的问题,将测试数据写到了文件里

      只想着测试时方便,却忘了程序是普遍使用的,功能是面向用户或者管理员的,而不是只有程序员可以使用的,不应该为了单纯的作业而却做作业。

5.2不足之处

      5.2.1 在添加数据或者查询数据的时候,没有做错误输入或错误查询的应对方案。

      5.2.2 时间原因,个人码代码速率也不是很高,上述那些错误都算是比较大的错误,花费了较多的时间在上面,以至于选做的功能,换乘功能没有完成,十分遗憾。

5.3 所得的收获

        5.3.1 一点点的编程思想

程序是用来用的,而不单单是为了测试而测试。

当拿到程序设计要求时,重要的是功能实现思路,而不是写了多少行代码作为判据。

      5.3.2 明白了继承的实际实现过程

      只是果然是用了才能学明白,看课本什么的也能看懂,但是心里总有点害怕,这怎么用啊,现在,继承已经不是那个不敢触碰的知识盲区。

      5.3.3 较熟练地掌握了快速查询与所指向向量下标的关系

      以前虽然也用map,但依然是遍历查找,没有实际意义,现在是直接指向下标,是真正意义上的“快速查找”。

      5.3.4 每一次大的作业都能让我加深对提前规划思路重要性的认识

      先大后小,由整体及部分,最后再细化。

5.4 对下一次课程设计的期待

      5.4.1 最希望的当然是时间充足一点,没有那么大的复习压力。

      5.4.2 希望下一次能够提前做好规划思路,写起来不那么眼高手低。

      5.4.3希望下一次可以对内存运营方式了解一下,那样应该会更容易找到错误的位置。

总结:

保持耐心和冷静,才能将程序写好,这两天看别人写的很快,就有些急,以至于在有些细节上埋了雷。还是很满足的,算是对自己这一年专业课学习的交代,仿佛推开了奇异世界大门的一条缝隙,会保持学习的热情的!

 

转载请注明原文地址: https://www.6miu.com/read-2650115.html

最新回复(0)