Fork me on GitHub

链表实现简单列车查询系统

利用C++链表知识实现简单的列车查询系统。

设计目的

综合运用链表知识解决实际问题的能力。


设计内容

设计火车售票处的计算机系统,可以为客户提供下列各项服务:

  1. 查询列车信息:根据旅客提出的起始站和终点站名,或者列车车次,输
    出下列信息:列车车次、发车时刻、到达时刻、运行时间,以及每个途经站点的
    站名、到达时间、发车时间、运行里程等信息;
  2. 录入列车信息;
  3. 修改列车信息;
  4. 删除列车信息;
  5. 浏览所有列车信息;
  6. 其它必要功能。

设计要求

  1. 要求采用链表方式存储所有列车车次基本信息(如车次名称等),对于其中的
    每个列车车次,也采用链表方式存储各个途经站点信息;
  2. 能够支持查询、修改、增加、删除等信息;
  3. 如有时间,建议提供保存和打开功能,用户可以把所有信息保存到硬盘文件
    上,也可以从硬盘文件上读取信息;
  4. 界面友好。

代码实现

station.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#pragma once
#include <string>
#include <sstream>

using std::ostream;
using std::string;
using std::stringstream;

//string类型的时间转换为int型分钟
inline int timeToMinute(string aTime){
string::iterator ite = aTime.begin();
int hour, minute;
while(ite != aTime.end()){
if(*ite == ':'){
stringstream hourStream(string(aTime.begin(), ite));
hourStream >> hour;
stringstream minuteStream(string(ite + 1, aTime.end()));
minuteStream >> minute;
return (hour * 60 + minute);
}
ite++;
}
return 0;
}

class Station{
public:
//有参构造函数
Station(string _stationName = "未命名站点", string _arrivalTime = "", string _leaveTime = ""){
stationName = _stationName;
arrivalTime = _arrivalTime;
leaveTime = _leaveTime;
pNextStation = NULL;
}

//复制构造函数
Station(Station &aStation){
this->stationName = aStation.stationName;
this->arrivalTime = aStation.arrivalTime;
this->leaveTime = aStation.leaveTime;
this->pNextStation = aStation.pNextStation;
}

//析构函数
~Station(){}

//重载输出运算符
friend ostream & operator<<(ostream &os, const Station &aStation){
os << aStation.stationName << '\t'
<< aStation.arrivalTime << '\t'
<< aStation.leaveTime;
return os;
}

//计算此站出发到下站抵达经历的时间
int calTime(){
if(this->pNextStation == NULL){
return 0;
} else {
int duringTime = timeToMinute(this->pNextStation->arrivalTime) - timeToMinute(this->leaveTime);
return (duringTime > 0) ? duringTime : duringTime + 24 * 60;
}
}

string stationName; //站名
string arrivalTime; //到达时间
string leaveTime; //出发时间
Station* pNextStation; //下一个站点
};

train.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#pragma once
#include "station.h"
#include <vector>
using std::vector;

class Train{
public:
//构造函数
Train(string _trainName = "未命名列车"){
trainName = _trainName;
stationNum = 0;
headStation = NULL;
pNextTrain = NULL;
}
//析构函数
~Train();
//添加站点
void insertStation(int locate, string _stationName = "未命名站点", string _arrivalTime = "未定义时间", string _leaveTime = "未定义时间");
//键盘添加站点
void keyboardInsertStation();
//删除站点
void deleteStation();
//改变站点信息
void changeStation();
//根据站点名称查询站点信息
void searchStationForName();
//打印该列车经过所有站点信息
void showAllStation();
//求列车经过站点个数
int getLength();
//重载运算符
friend ostream & operator<<(ostream &os, const Train &aTrain);
//更新运行里程和时间
void updateInfo();

string trainName; //列车车次
int stationNum; //站点个数
Station* headStation; //头站点
Train* pNextTrain; //下一列列车

//vector <int> mileag; //运行里程
vector <int> time; //运行时间
};

train.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "train.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;

//更新运行里程和时间
void Train::updateInfo(){
Station *myStation = this->headStation;
//清空容器
this->time.clear();
while(myStation){
//插入时间
this->time.push_back(myStation->calTime());

myStation = myStation->pNextStation;
}

}

//重载运算符
ostream & operator<<(ostream &os, const Train &aTrain) {
Station *p = aTrain.headStation;
while(p){
os << aTrain.trainName << '\t' << *p << '\t' << p->calTime() <<endl;
p = p->pNextStation;
}
return os;
}

//求列车站点长度
int Train::getLength(){
return this->stationNum;
}

//添加站点
void Train::insertStation(int locate, string _stationName, string _arrivalTime, string _leaveTime){
if (locate > this->stationNum + 1 || locate < 1) {
cout << "ERROR:超出行程表范围!" << endl;
}
else if (this->headStation != NULL && locate > 1) {
//new一个新站
Station* aStation = new Station(_stationName, _arrivalTime, _leaveTime);
//将新站加入列车行程表中
Station* p = this->headStation;
while (locate - 2) {
p = p->pNextStation;
locate--;
}
aStation->pNextStation = p->pNextStation;
p->pNextStation = aStation;
this->stationNum++;
this->updateInfo();
cout << "加入新站成功!" << endl;
} else if (this->headStation != NULL && locate == 1){
//new一个新站
Station* aStation = new Station(_stationName, _arrivalTime, _leaveTime);
//将新站加入列车行程表中
Station* p = this->headStation;
this->headStation = aStation;
aStation->pNextStation = p;
this->stationNum++;
this->updateInfo();
cout << "加入新站成功!" << endl;
} else {
//new一个新站
Station* aStation = new Station(_stationName, _arrivalTime, _leaveTime);
//将新站加入列车行程表中
this->headStation = aStation;
this->stationNum++;
this->updateInfo();
cout << "加入新站成功!" << endl;
}
}

//键盘增加站点
void Train::keyboardInsertStation()
{
int locate;
cout << "请输入插入的位置:";
cin >> locate;
string _stationName, _arrivalTime, _leaveTime;
cout << "请分别输入 站点名称 到达时间 出发时间 :" << endl;
cin >> _stationName >> _arrivalTime >> _leaveTime;

this->insertStation(locate, _stationName, _arrivalTime, _leaveTime);
}

//删除站点
void Train::deleteStation(){
int locate;
cout << "请输入插入的位置:";
cin >> locate;
if(locate > this->stationNum || locate < 1){
cout << "ERROR:超出行程表范围!" << endl;
}else if(this->headStation != NULL && locate > 1){
Station* p = this->headStation;
while(locate - 2){ //到达第i-1个结点,p->pNextStation为欲删除的结点的指针
p = p->pNextStation;
locate--;
}
Station* q = p->pNextStation;
p->pNextStation = p->pNextStation->pNextStation;
delete q;
this->stationNum--;
this->updateInfo();
cout << "删除站点完成!" << endl;
} else if(this->headStation != NULL && locate == 1){
Station* p = this->headStation;
this->headStation = p->pNextStation;
delete p;
this->stationNum--;
this->updateInfo();
cout << "删除站点完成!" << endl;
} else {
cout << "列车站台为空!" << endl;
}
}

//析构函数
Train::~Train(){
if(this->headStation == NULL){
} else{
Station* p = this->headStation;
Station* q;
while (p){
q = p;
p = p->pNextStation;
delete q;
}
}
}

//改变站点信息
void Train::changeStation()
{
int locate;
cout << "请输入需要改变站台所在的位置:";
cin >> locate;
if(locate > this->stationNum || locate < 1){
cout << "ERROR:超出行程表范围!" << endl;
return;
}else{
Station* p = this->headStation;
while(locate - 1){
p = p->pNextStation;
locate--;
}
cout << *p << endl;
cout << "1. 站点名称\n2. 列车到达时间\n3. 列车出发时间\n";
cout << "站点已找到,请选择改变的信息:";

int choose;
string changeValue;
cin >> choose;
switch(choose){
case 1:
cout << "请输入新的站名:";
cin >> changeValue;
p->stationName = changeValue;
cout << "修改完成!" << endl;
break;
case 2:
cout << "请输入新的到达时间:";
cin >> changeValue;
p->arrivalTime = changeValue;
cout << "修改完成!" << endl;
this->updateInfo();
break;
case 3:
cout << "请输入新的出发时间:";
cin >> changeValue;
p->leaveTime = changeValue;
cout << "修改完成!" << endl;
this->updateInfo();
break;
default:
cout << "未更改数据,请输入正确的数字!" << endl;
}
}
}

//根据站点名称查询站点信息
void Train::searchStationForName() {
string _stationName;
cout << "请输入要查询的站名:" ;
cin >> _stationName;
Station* p = this->headStation;
if (p == NULL) {
cout << "行程表为空!" << endl;
}
int count = 1; //计数器
while (p) {
if (p->stationName == _stationName) {
cout << "该站点为行程表第" << count << "个站点\n站点名称为:"
<< p->stationName << "\n列车到达时间为:"
<< p->arrivalTime << "\n列车出发时间为:"
<< p->leaveTime << endl;
}
count++;
p = p->pNextStation;
}
cout << "未找到该站点的信息!" << endl;
}

//打印该列车所有站点
void Train::showAllStation() {
cout << this->trainName << " 的行程表为:" << endl;
cout << "列车信息 站点名称 到站时间 出发时间 到达下站所需时间(min)" << endl;
cout << *this << endl;
}

schedule.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#pragma once
#include "train.h"

class Schedule{
public:
//构造函数
Schedule(string _scheduleName = "未命名时刻表"){
scheduleName = _scheduleName;
trainNum = 0;
headTrain = NULL;
}
//析构函数
~Schedule();
//添加列车
Train* insertTrain(int locate, string _trainName = "未命名列车");
//键盘添加站点
void keyboardInsertTrain();
//文本添加站点
void txtInsertTrain(string filename);
//文本输出站点
void scheduleToTxt(string filename);
//删除列车
void deleteTrain();
//改变列车站点信息
void changeTrainStation();
//改变列车名称
void changeTrainName();
//根据列车名称查询站点信息
Train* searchTrainForName();
//打印所有列车经过所有站点信息
void showAllTrain();
//求列车个数
int getLength();
//操作菜单
void operateTheSchedule();
//重载运算符
friend ostream & operator<<(ostream &os, const Schedule &aSchedule);

private:
string scheduleName; //列车车次
int trainNum; //站点个数
Train* headTrain; //头站点
};

schedule.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#include "schedule.h"
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::ofstream;

//重载运算符
ostream & operator<<(ostream &os, const Schedule &aSchedule) {
Train *p = aSchedule.headTrain;
while (p) {
os << *p;
p = p->pNextTrain;
}
return os;
}

//求列车长度
int Schedule::getLength(){
return this->trainNum;
}

//添加列车
Train* Schedule::insertTrain(int locate, string _trainName){
if (locate > this->trainNum + 1 || locate < 1) {
cout << "ERROR:超出行程表范围!" << endl;
return NULL;
}
else if (this->headTrain != NULL && locate > 1) {
//new一个新列车
Train* aTrain = new Train(_trainName);
//将新列车加入列车行程表中
Train* p = this->headTrain;
while (locate - 2) {
p = p->pNextTrain;
locate--;
}
aTrain->pNextTrain = p->pNextTrain;
p->pNextTrain = aTrain;
this->trainNum++;
cout << "加入新列车成功!" << endl;
return aTrain;
} else if(this->headTrain != NULL && locate == 1){
//new一个新列车
Train* aTrain = new Train(_trainName);
//将新列车加入列车行程表中
Train* p = this->headTrain;
this->headTrain = aTrain;
aTrain->pNextTrain = p;
this->trainNum++;
cout << "加入新列车成功!" << endl;
return aTrain;
} else {
//new一个新列车
Train* aTrain = new Train(_trainName);
//将新站加入列车行程表中
this->headTrain = aTrain;
this->trainNum++;
cout << "加入新列车成功!" << endl;
return aTrain;
}
}

//键盘增加列车
void Schedule::keyboardInsertTrain()
{
int locate;
cout << "请输入插入的位置:";
cin >> locate;
string _trainName;
cout << "请输入列车名称:" ;
cin >> _trainName;

this->insertTrain(locate, _trainName);
}

//文本添加站点
void Schedule::txtInsertTrain(string filename){
ifstream infile;
infile.open(filename + ".txt");
if(!infile){
cout << "ERROR:打开 " << filename << ".txt 文件失败" << endl;
return;
}
//_lastTrainName用于优化查找速度,但不可用于多次文本输入内存
string _trainName, _stationName, _arrivalTime, _leaveTime, _lastTrainName;
if(this->headTrain == NULL){
_lastTrainName = "";
}else{
_lastTrainName = this->headTrain->trainName;
}
while(infile >> _trainName>> _stationName>>_arrivalTime>>_leaveTime){
if(_trainName == _lastTrainName){
Train *p = this->headTrain;
while (p) {
if (p->trainName == _trainName) {
p->insertStation(p->stationNum+1, _stationName, _arrivalTime, _leaveTime);
break;
}
p = p->pNextTrain;
}
} else {
Train *p = this->insertTrain(this->trainNum+1, _trainName);
p->insertStation(p->stationNum+1, _stationName, _arrivalTime, _leaveTime);
_lastTrainName = _trainName;
}
}
infile.close();
}

//文本输出信息
void Schedule::scheduleToTxt(string filename){
ofstream outfile;
outfile.open(filename + ".txt");
if (!outfile) {
cout << "ERROR:打开 " << filename << ".txt 文件失败" << endl;
return;
}
outfile << *this;
outfile.close();

}

//删除站点
void Schedule::deleteTrain(){
int locate;
cout << "请输入删除的位置:";
cin >> locate;
if(locate > this->trainNum || locate < 1){
cout << "ERROR:超出行程表范围!" << endl;
}else if(this->trainNum != NULL && locate > 1){
Train* p = this->headTrain;
while(locate - 2){ //到达第i-1个结点,p->pNextTrain为欲删除的结点的指针
p = p->pNextTrain;
locate--;
}
Train* q = p->pNextTrain;
p->pNextTrain = p->pNextTrain->pNextTrain;
//删除列车的站点
while(q->stationNum){
Station* delSta;
delSta = q->headStation;
q->headStation = q->headStation->pNextStation;
delete delSta;
q->stationNum--;
}
//删除列车
delete q;
this->trainNum--;
cout << "删除列车完成!" << endl;
} else if (this->trainNum != NULL && locate == 1){
Train* p = this->headTrain;
this->headTrain = p->pNextTrain;
//删除列车的站点
while (p->stationNum) {
Station* delSta;
delSta = p->headStation;
p->headStation = p->headStation->pNextStation;
delete delSta;
p->stationNum--;
}
//删除列车
delete p;
this->trainNum--;
cout << "删除列车完成!" << endl;
} else{
cout << "行程表为空!" << endl;
}
}

//析构函数
Schedule::~Schedule(){
if (this->headTrain == NULL) {
}else {
Train* p = this->headTrain;
Train* q;
while (p) {
q = p;
p = p->pNextTrain;
delete q;
}
}
}

//改变列车信息
void Schedule::changeTrainStation()
{
Train* p = this->searchTrainForName();
if(p != NULL){
while (1)
{
cout << " ******************************************************" << endl;
cout << " * 列车查询系统子菜单 *" << endl;
cout << " * *" << endl;
cout << " * 您现在正在操作 " << p->trainName << " 列车 *" << endl;
cout << " * 请输入对应功能的数字完成操作 *" << endl;
cout << " * 1.添加站点信息 *" << endl;
cout << " * 2.删除站点信息 *" << endl;
cout << " * 3.修改站点信息 *" << endl;
cout << " * 0.退出子菜单 *" << endl;
cout << " * *" << endl;
cout << " * 列车 "<< p->trainName << " 现有站台 "<<p->getLength() <<" 个 *" << endl;
cout << " ******************************************************" << endl;

int choice;
cout << "请输入您的选项:";
cin >> choice;
switch (choice)
{
case 1:
p->keyboardInsertStation(); break;
case 2:
p->deleteStation(); break;
case 3:
p->changeStation(); break;
case 0:
return;
default:
cout << "输入选项非法!请重新输入!" << endl;
break;
}
}

}
}

//查询列车具体信息
Train* Schedule::searchTrainForName() {
string _trainName;
cout << "请输入要查询的列车名:" ;
cin >> _trainName;
Train* p = this->headTrain;
if (p == NULL) {
cout << "行程表为空!" << endl;
return p;
}
int count = 1; //计数器
while (p) {
if (p->trainName == _trainName) {
cout << *p << endl;
return p;
}
count++;
p = p->pNextTrain;
}
cout << "未找到该列车的信息!" << endl;
return p;
}

//改变列车名称
void Schedule::changeTrainName(){
Train* p = this->searchTrainForName();
if (p != NULL) {
cout << "列车已找到,请输入新的列车名:";
string _trainName;
cin >> _trainName;
p->trainName = _trainName;
cout << "修改成功!" << endl;
}
}


//打印所有列车所有站点
void Schedule::showAllTrain() {
cout << this->scheduleName << " 的行程表为:" << endl;
cout << "列车信息\t站点名称\t到站时间\t出发时间" << endl;
cout << *this;
}

//操作菜单
void Schedule::operateTheSchedule() {
while (true)
{
int choice;
cout << " ******************************************************" << endl;
cout << " * 列车查询系统 *" << endl;
cout << " * *" << endl;
cout << " * 请输入对应功能的数字完成操作 *" << endl;
cout << " * 1.键盘添加列车信息 *" << endl;
cout << " * 2.文本添加列车信息 *" << endl;
cout << " * 3.删除列车信息 *" << endl;
cout << " * 4.修改列车名称信息 *" << endl;
cout << " * 5.修改列车站点具体信息 *" << endl;
cout << " * 6.输出行程表信息 *" << endl;
cout << " * 0.退出系统 *" << endl;
cout << " * *" << endl;
cout << " * 目前共有" << this->getLength() << "辆列车 *" << endl;
cout << " ******************************************************" << endl;

cout << "请输入您的选项:";
cin >> choice;
switch (choice)
{
case 1:
this->keyboardInsertTrain(); break;
case 2:
{
cout << "请输入要打开的文件名:";
string filename;
cin >> filename;
this->txtInsertTrain(filename);
break;
}
case 3:
this->deleteTrain(); break;
case 4:
this->changeTrainName(); break;
case 5:
this->changeTrainStation(); break;
case 6:
this->showAllTrain(); break;
case 0:
{
cout << "您需要保存该行程表吗?(Y/N)\t";
char c;
cin >> c;
if (c == 'Y' || c == 'y')
{
cout << "请输入文件名:";
string filename;
cin >> filename;
this->scheduleToTxt(filename);
return;
}
return;
}
default:
cout << "输入选项非法!请重新输入!" << endl;
break;
}
}
}

main.cpp

1
2
3
4
5
6
7
8
#include "schedule.h"

int main(){
Schedule mySchedule("我的行程表");
mySchedule.operateTheSchedule();
system("pause");
return 0;
}
扫描二维码,拯救贫困山区大学生!
-------------本文结束感谢您的阅读-------------