公交查询系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南京航空航天大学计算机实践实验报告
课程名称:软件技术基础
专题:学生成绩管理系统
学生姓名:孟宁·罗龙城
班级学号: 030950111 ·030950120 专业名称:探测制导与控制
2011年11月
一`引言
1.1编写目的
在当今社会中,交通问题已经成为很重要的社会性问题,而公交成为解决交通问题的一个关键因素。
大力发展公共交通是解决城市交通拥挤问题的首选措施。
但是一种公交是不能满足所有人的出行需求的,人们可能无法通过乘坐一辆公交车到达目的地,这时候就需要换乘来解决该问题,经调查路程最短和换乘次数是人们最关心的问题。
根据这些问题,需要开发一套公交查询系统,从而方便人们出行前进行查询。
1.2项目背景
本系统主要面向广大的城市居民和外来的旅游者,为不同需求的用户提供全面、准确的公交信息。
在该系统中还需要提供多种公交查询方式,并且该系统中要给出管理功能,方便公交发生变化后及时对路线进行调整。
根据需求我们可以将系统分为两大功能模块,分别是前台查询公交模块和后台公交管理模块。
下面分别来看一下两个模块的具体功能。
前台公交查询模块:该模块是被普通用户使用的,其中包括线路查询、站点查询、站站查询等多种核心公交查询功能。
后台公交管理模块:该模块是由系统管理员操作的,包括站点管理和路线管理两大功能。
在站点功能中包括向新线路中添加站点和修改原线路站点的功能。
在线路管理中包括修改线路原有信息的功能,其信息包括起始和结束时间、起始站和终点站等。
开发软件名称:南京市公交线路查询系统
项目任务提出者:计算机指导老师储剑波
项目开发者:罗龙成孟宁
用户:暂无
实现软件单位:南京航空航天大学
项目与其他软件系统关系:本项目以Microsoft Visual C++为开发环境。
1.3定义
(1)数据流图:
描绘系统的逻辑模型,图中没有任何具体的物理元素,只是描绘信息在系统中流动和处理的情况,它表示了数据和处理过程的关系。
数据流图有四种基本符号:
● 正方形(或立方体)表示数据的源点或终点。
● 圆角矩形(或圆形)代表变换数据的处理。
处理不一定是一个程序。
一个处理框可以代表一系列程序,单个程序或者程序的
一个模块;它甚至可以代表一种人工处理过程。
● 开口矩形(或两条平行横线)代表数据存储。
数据存储可以表示一个文件,文件的一部分,数据库的元素或纪录的一部分等等。
数据存储是处于静止状态的数据。
● 箭头代表数据流,即特定数据的流动方向。
数据流是处于运动中的数据。
还有几种附加符号:
● 星号表示数据流之间是“与”关系
● 加号表示“或”关系
● 异或符号表示只能从中选一个
(2)数据字典:
是对系统中各类数据描述的集合,是各类数据属性清单,是进行详细的数据收集和数据分析所获得的主要结果。
它通常包括以下五个部分:
● 数据项,是数据的最小的单位。
● 数据结构,是若干数据项有意义的集合。
● 数据流,可以是数据项,也可以是数据结构,表示某一处理
过程的输入或输出。
● 数据存储,处理过程中存取的数据。
常常是手工凭证,手工
文档,计算机文件。
● 处理过程。
它们的描述内容如下:
1.数据项描述={数据项名,数据项含义说明,别名,类型,长度,取值范围,与其他数据项的逻辑关系}
取值范围,与其他数据项的逻辑关系定义了数据的完整性约束条件,是设计数据检验功能的依据。
2.数据结构描述={数据结构名,含义说明,组成:{数据结构或数据项}}
3.数据流={数据流名,说明,流出过程,流入过程,组成:{数据结构或数据项}}
● 流出过程,说明该数据流由什么过程来。
● 流入过程,说明该数据流到什么过程去。
4.数据存储={数据存储名,说明,输入数据流,输出数据流,组成:{数据结构或数据项},数据量,存取方式}
● 数据量,说明每次存取多少数据,每天(或每小时,或每
周)存取几次的信息。
存取方法,指的是批处理,还是联机处理;是检索还是更新;是顺序检索还是随机检索;尽可能详细收集并加以说明。
5.处理过程={处理过程名,说明,输入:{数据流},输出:{数据流},处理:{简要说明}}
简要说明中主要说明该处理过程的功能,即“做什么”(不是怎么做);处理频度要求,如每小时(或每分钟)处理多少事务,多少数据量;响应时间要求等。
这些处理要求是后面物理设计的输入及性能评价的标准。
1.4参考资料
1、《软件技术基础教程》,万晓东、施玉霞、孔德明,南京航空航天大学。
2、《C++程序设计教程》,皮德常,机械工业出版社。
3、《ML用户指南》,Grady Booch James Rumbaugh Ivar Jacobson
著,邵维忠等译。
4、《软件工程导论》(第五版),张海藩著,清华大学出版
社。
5、《Visual C++实用教程》,丁有和郑进周怡君著,电子
工业出版社。
6、《算法设计与分析》,王红梅著,清华大学出版社。
7、《数据库系统概论》(第四版),王珊萨师煊著,高等教
育出版社
二、可行性分析
可行性研究的前提
2.1 要求:
2.1.1 功能:使用人员通过此软件使出行轻松方便。
2.1.2 性能:查询效率尽可能做到精准,信息维护功能做到简单易用。
2.1.3 输入:简单、易用。
2.1.4 输出:快速、精确。
2.1.5完成期限:4个月
2.1.6基本数据处理流程
2.2目标:开发出一套用于公交车查询的软件,帮助出行人员方便、高效的进行对自己的出行管理,并通过此次软件开发过程全面提高自身的综合素质。
2.3条件、假定和限制:
开发时间:5周。
最迟完成时间:2011年11月25 日
2.3 决定可行性的主要因素:资金到位、现有技术可完全承担开发任务、软件能被原有工作人员快速接受。
2.4进行可行性研究的方法
通过调查分析宝鸡市公交车查询系统现阶段所具备的能力及实现的方法、确定主体结构。
利用JAVA和数据库编程所能达到的能力,以最简洁、最容易的办法,边开发边测试,实现一个初级应用软件。
即采用面向对象的方法开发此软件。
2.5评价尺度
以能够达到帮助出行人员提高行程管理效率、减少额外人力、物力资源开销为评价标准。
3.对现有系统的分析
目前市场存在的公交查询系统软件,大多是公交公司提供,为网络版。
实时性好是他们的优势,但是存在以下问题:
3.1产品的交互界面方面。
公交公司所提供的网络版查询系统在很大程度上只是为了使用,对交互界面的设计并没有从用户的方面过多考虑。
3.2产品的功能方面。
在前期的市场调查中,我们发现网络版查询系统具有或多或少的各方缺陷。
如只提供终点起点的查询,在起点和终点之间的中间站没有提供查询。
在起点和终点没有直达车时,无法提供相关的转车信息。
在查询时显示不直接、明确等问题。
3.3产品的优化方面。
对一个初级系统是无法做到尽善尽美的,因此要在用户的使用过程中发现问题,从而进行基本结构的添加、修改,对应用软件进行优化、升级。
网络版的查询系统是无法做到这一点的。
4.技术可行性分析
公交查询系统编程已经具备了完备、成熟的理论和体系结构,JAVA编程与数据库相结合进行开发的技术也日趋成熟,在以上限制条件下利用现有技术和人员,本系统的开发完全可行。
4.1 与工程产品相关的关键技术概述
本工程产品的关键技术在于JAVA编程的程序设计与数据库的结合,将所有的数据信息都放入数据库中进行存储,而这些数据信息的调用则完全由程序来完成,即“程序设计数据化,数据管理程序化”思想。
4.2关键技术的理论基础
依据“程序设计数据化,数据管理程序化”的设计思想,将数据库文件与程序设计紧密的集合在一起。
4.3技术可行性评价完全可以实现预期目标。
5.投资及效益分析(略)
6.社会因素方面可行性
6.1公交车应用普及,对个人的出行参考的合理化是可行的;
6.2该产品使用简单方便,略懂计算机的用户就可以没有任何困难地使用该产品;
7.结论
技术、经济、操作都有可行性,可以立即开始进行。
三、需求分析
随着我国经济的高速发展,人们生活水平的提高,越来越多的人开始热衷于到外地旅游。
那么对于这些外来旅游者,首先搞清这个城市的公交路线显的很重要!南京,作为一个六朝古都,每年都要吸引大量的游客,为了满足这些游客熟
悉公交路线的需求,特以公交查询系统为设计课题。
本软件不仅能给游客带来方便,也能给广大市民提供方便。
我认为这样的系统应该具有很好的实用性!开发本系统的目标就是立足广大乘客的实际,着眼于公交业的未来发展,规范公交管理,提高服务质量,方便乘客查询,并为此设计该系统。
3.1 用户功能需求分析
3.1.1所有乘客可以使用该系统进行车次及路线的查询。
3.1.2本系统应具有简单易用功能强大特点,有较强的纠错能力(随着软件的版本升级功能和纠错能力也可以不断得到提高)。
如果在网络上运行,应有数据在线更新的能力以及在线查询的能力。
由于毕业设计时间有限,本系统没有设计成网络运行版的,在以后的时间会进一步完善该系统。
3.1.3由于车次经常会变化所以需要一个管理员身份去管理这个公交查询系统方便更改车次的信息以及车辆的出行线路。
3.2 系统功能分析
本系统提供了的车次查询功能、路线查询功能。
乘客可以方便的进行查询,以防乘错车次。
同时管理员身份方便管理车辆的车次和出行线路。
当然有些功能的智能化不是很强,系统有待进一步来完善。
也希望老师及朋友给予指导,提出您们的建议!在此,先向您们表示感谢!
3.3.1档案(公交路线信息资料)管理模块:一般浏览者只能查看档案,不能对档案做任何的修改。
不同的用户级别所操作的档案类型是有限制的。
管理员用户可向里面添加、修改和删除档案。
也可设置档案级别,以加强它们的保密性。
3.3.2查询管理模块:是给管理员用的,是为了方便管理员查找档案,也有关键字搜索和模糊搜索。
查到记录后,也可双击记录即可显示详细信息。
3.3.3系统维护模块:仅限管理员使用。
其中可以添加、修改、删除操作员工,设置他们的权限、级别及密码。
3.4对性能的规定
3.2.1数据精确度:查询时要保证查全率,所有相应域包含查询关键字的记录都应能查到。
因为通常有文件的记录会很多,所以本系统采用了两种方法进行查询:直接查询和模糊查询。
3.4.2时间特性:一般操作的响应时间应在1~2秒内。
3.5基本数据处理流程
3.6输入输出要求:输入操作简便,容错性好,输出界面给人以全新的感觉,一目了然。
给操作用户带来了极大的便利,对用户友好。
对鼠标和键盘单独支持。
3.7数据管理能力要求:系统管理员可以及时对数据进行更新(添加、修改、删除等),同时对数据进行权限设置、安全设置以及备份等操作。
3.8故障处理要求:正常使用时不应出错,若运行时遇到不可恢复的系统错误,也必须保证数据库完好无损。
3.9其他要求
3.9.1系统的容错性: 用户输错数据都有提示信息,具有较好的容错性能。
3.9.2系统的封闭性: 用户的封闭性较好,用户基本上在提示信息下输数据。
3.8数据字典与流图
2公交站点查询程图:
3公交线路查询流程图:
4公交换乘方案流程图:系统数据字典,如下表所示。
数据项数据项关键字数据项含义数据
类型
数据要求
系统管理员编号AdminID 管理员的唯一编号整型
1.2.3.4
…
系统管理员用户名Adiminname 管理员用户名
字符
型
2-50
系统管理员密码Adminpw 管理员密码
字符
型
2-50
普通用户编号UserID普通用户的唯一编号整型
1.2.3.4
…
普通用户用户名Username 普通用户用户名
字符
型
2-50
普通用户密码Userpw 普通用户密码
字符
型
2-50
线路编号RouteID 每一条线路的编号整型 1.2.3.4…线路名称Routename 每一条线路的名称字符50
四概要设计说明书
4.1需求规定
表1 输入输出需求
4.2运行环境
客户端适用于所有运行JVM的机器上。
4.3基本设计概念和处理流程
图2 总体处理流程图
4.4结构
2.5功能需求与程序的关系(略)
2.6人工处理过程
向数据库插入必要的线路信息。
2.7尚未问决的问题(无)
4、5接口设计
4.5.1用户接口
本系统只实现查询功能,故根据用户在GUI中输入的查询信息提供具体回答。
其中,输入车次为数字型字符,站点为字符串类型。
输入信息具体见表1。
3.2外部接口(略)
3.3内部接口(略)
4、6运行设计
4.6.1运行模块组合
程序初始化后,启用输入接受数据。
判断接受的数据从而调用不同模块产生各自进程和功能。
实时反馈信息、更新界面。
4.6.2运行控制
运行控制以接受键盘事件和鼠标事件来控制。
信息反馈方面通过不同的模块功能,实现信息更新显示等。
4.6.3运行时间(略)
4.7系统数据结构设计
4.7.1逻辑结构设计要点
gjc_down公交车下行线路表(可能不需要)
表3数据库逻辑结构图表
4.7.2物理结构设计要点
系统的物理结构具体由数据库来设计与生成,此处略。
4.7.3数据结构与程序的关系(略)
4、8系统出错处理设计
4.8.1出错信息
1)JTextField1输入格式不是数字型字符。
2)JTextField2、JTextField3输入格式不是字符串类型。
3)JTextField1、 JTextField2及JTextField3的输入的相关信息不存在。
处理:弹出对话框显示“抱歉:xxx站不存在!”或“抱歉:xx车次不存在!”。
五、测试结果及分析
在上述运行环境下运行程序,会相继得到下面的各种运行结果。
按提示语进行操作;
如在主菜单选项下,选择1会进入“公交线路查询”功能选项下,再次按提示语操输入要查询的公交路线,如8路就输入8,就会显示8路所经过的站点。
六、设计总结
这次完成的这个学生成绩管理系统确实给我留下了很深的印象,也让我更深刻的认识到了动手的必要性。
一方面,这次的这个作业锻炼了我自己的动手能力和动脑能力,使自己可以在电脑前静下心来认真的思考学习,领会老师讲过的设计思想,从而锻炼自己编程的能力。
虽然平时也会写些小的程序,但都达不到锻炼自己的目的,往往由于过于急躁而放弃,但是。
这次我强迫自己必须静下心一点点做成了,有一种成就感。
但更多的是锻炼了自己的思维能力和动手能力和分析解决问题的能力。
另一方面,我体会最深的那就是一个我们必须学会调试自己的程序,当遇到输出结果和预想的有出入是,自己经过思考一点一点的去调试自己的程序,找出问题的所在,然后静下心慢慢的解决它,我觉得这是一个程序员必须具备的能力。
出错了并不可怕,要自己一点一点的解决。
另外,在做之前,一定要先明白目的,这样设计起来才有根据,设计出来的系统才能是正确的
总之,经过我的努力,算是完成了这一次的作业,不能说圆满,因为有些思想是借鉴的参考书上的,但起码我真真切切的自己实践
了,自己也掌握了一些方法和技巧,对软件的了解也有了更深一层的认识;比如以前从不认为编程之后还要写文档;但经过这次的文档编写使得我很快就为编写程序开了一个好头;比没写文档的时候还要快;因为思路理清楚了;结果编出来的程序也没有太多的错误需要一个个查;希望老师以后多多举行一些这种独立完成一个系统的作业;让我们不再对单独完成整套系统不再恐惧。
七附录:
/源代码*
公交查询系统源代码
此文件中包含改程序的所有代码;
用户模块的子模块包括:公交换乘、公交线路、公交站点.
编码主程序主菜单:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#include "queue.h"
#define MAX_NUM_OF_BUS_STATIONS 4000
typedef struct {
char name[50];
int staNum,staOrd[100];//依附于某条线路的站点集合
}Line;
typedef struct {
char name[50];
int lineNum,line[400];//依附于某站点的线路集合
}Station;
int g_StaNum,g_LineNum; //车站数目、行车路线书目
Station g_Station[MAX_NUM_OF_BUS_STATIONS];
Line g_Line[400];
Hash g_Hash; //用于查找站点对应序号的哈希表
//将str按空格分隔成若干车站,并将站编号
void SliceOff(char *str)
{
bool firstIn;
int len,p,ps,order,ignore;
char staName[50];
g_LineNum++;
len = strlen(str) - 1;//最后一个字符时回车,减去它。
p = -1; //此处与 do while结合,能教巧妙的处理末尾的切割
ps = 0;
firstIn = true;
do {
p++;
if((str[p]==' ') || (p==len)) //已切好一个完整的站名
{
staName[ps] = '\0';
ps = 0;
if(firstIn)
{
firstIn = false;
strcpy(g_Line[g_LineNum].name, staName);
}
else
{
if(!g_Hash.Search(staName, order, ignore)) //若不在表中,则增加新的车站
{
order = ++g_StaNum;
strcpy(g_Station[order].name, staName);
g_Hash.Insert(staName, order);
}
g_Line[g_LineNum].staOrd[ g_Line[g_LineNum].staNum++ ] = order; //看清楚
g_Station[order].line[ g_Station[order].lineNum++ ] = g_LineNum; //看清楚
}
}
else
{
staName[ps++] = str[p];
}
} while(p<len);
}
//递归输出乘车路线
void PrintPath(int pos, int *preS, int *preL)
{
if(preS[pos])
{
PrintPath(preS[pos], preS, preL);
printf(" 从[ %s ]站乘坐[ %s ]号线路,到达[ %s ]站\n",g_Station[preS[pos]].name, g_Line[preL[pos]].name, g_Station[pos].name); }
}
//计算并输出两点间的最佳路线
void calc(int const c,int const d)
{
Queue queue;
int i,j,k,count;
int tmpSta,tmpLine;
bool *visited;
int *pSta, *pLine;
visited = (bool *) malloc((g_StaNum+10) * sizeof(bool));
pSta = (int *)malloc((g_StaNum+10) * sizeof(int));
pLine = (int *)malloc((g_StaNum+10) * sizeof(int));
for(i=1; i<=g_StaNum; i++)
{
visited[i] = false;
pSta[i] = 0;
pLine[i] = 0;
}
count = -1;
visited[c] = true;
queue.En(c);
while(!queue.Empty())
{
count++;
queue.De(k);
for(i=0; i<g_Station[k].lineNum; i++) //k站可以使用的线路
{
tmpLine = g_Station[k].line[i];
for(j=0; j<g_Line[tmpLine].staNum; j++) //第i条线路能到达的站
{
tmpSta = g_Line[tmpLine].staOrd[j];
if(!visited[tmpSta])
{
visited[tmpSta] = true;
queue.En(tmpSta);
pSta[tmpSta] = k;
pLine[tmpSta] = tmpLine;
}
}
}
}
PrintPath(d,pSta,pLine);
free(visited);
free(pSta);
free(pLine);
}
int main()
{
FILE *fi = fopen("in.txt","r");
char str[1024];
int ignore,current,destination;
while(fgets(str, 1024, fi))
{
SliceOff(str); //将车站名从字符串中切出来,并保存站名对应的序号
}
while(1)
{
printf("=========================================================\n"); printf("请输入您所在的站点:");
scanf("%s", &str);
if(!g_Hash.Search(str, current, ignore))
{
printf("该位置不存在!\n");
}
else
{
printf("请输入您想到的站点:");
scanf("%s", &str);
if(!g_Hash.Search(str, destination, ignore))
{
printf("该位置不存在!\n");
}
else
{
calc(current, destination);
}
}
printf("=========================================================\n");
system("pause");
system("cls");
}
return 0;
}
被调用头文件
1、#ifndef HASH_H
#define HASH_H
#include <stdlib.h>
#define HASHSIZE 12017
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE 0
typedef struct {
int ord;
char staName[50];
}HashType;
class Hash
{
public:
Hash();
~Hash();
bool Search(char *key, int &e,int &p);
bool Insert(char *key, const int e);
private:
unsigned int JSHash(char *key);
void Collision(int &p);
HashType *hashList;
bool *used;
};
#endif
//--构造函数。
初始化变量
Hash::Hash()
{
int i;
hashList = (HashType *)malloc(HASHSIZE * sizeof(HashType)); used = (bool *)malloc(HASHSIZE * sizeof(bool));
for(i=0; i<HASHSIZE; i++)
{
hashList[i].ord = 0;
hashList[i].staName[0] = '\0';
used[i] = false;
}
}
//--析构函数。
释放空间
Hash::~Hash()
{
free(hashList);
free(used);
}
//JSHash
unsigned int Hash::JSHash(char *str)
{
unsigned int hash = 1315423911;
while(*str)
{
hash ^=((hash<<5) + (*str++) + (hash>>2));
}
return (hash&0x7FFFFFFF);
}
//线性探测
void Hash::Collision(int &p)
{
p = (p+1) % HASHSIZE;
}
//以key查找数据,并返回到e
bool Hash::Search(char *key, int &e,int &p)
{
p = JSHash(key) % HASHSIZE;
while(used[p] && strcmp(key, hashList[p].staName)!=0) {
Collision(p);
}
if(strcmp(key, hashList[p].staName)==0)
{
e = hashList[p].ord;
return SUCCESS;
}
else
{
return UNSUCCESS;
}
}
//以key定址,并保存e的数据到表中
bool Hash::Insert(char *key, const int e)
{
int t,p;
if(Search(key, t, p))
{
return DUPLICATE;
}
else
{
hashList[p].ord = e;
strcpy(hashList[p].staName, key);
used[p] = 1;
return SUCCESS;
}
}
2、#ifndef QUEUE_H
#define QUEUE_H
#include <stdlib.h>
#define OVERFLOW 0
#define SUCCESS 1
#define UNSUCCESS 0
typedef struct QNode{
int data;
struct QNode *next;
}QNode;
class Queue
{
public:
Queue();
~Queue();
bool En(const int e);
bool De(int &e);
bool Empty();
private:
QNode *front;
QNode *rear;
};
#endif
//--构造函数。
Queue::Queue()
{
front = rear = (QNode *)malloc(sizeof(QNode)); if(!front) exit(OVERFLOW);
front->next = NULL;
}
//--析构函数。
Queue::~Queue()
{
free(rear);
}
//入队列操作。
bool Queue::En(const int e)
{
QNode *p;
p = (QNode *)malloc(sizeof(QNode));
if(!p)
{
return UNSUCCESS; }
p->data = e;
p->next = NULL;
rear->next = p;
rear = p;
return SUCCESS;
}
//出队列操作
bool Queue::De(int &e) {
QNode *p;
if(front == rear)
{
return UNSUCCESS; }
p = front->next;
e = p->data;
front->next = p->next; if(rear == p)
{
rear = front;
}
free(p);
return SUCCESS;
}
//判断队列为空操作
bool Queue::Empty()
{
if(front == rear)
{
return true;
}
return false;
}
3数据文件
另有电子版WORD文档。