• 项目目的
  1. 了解地图管理系统的功能需求,进行功能模块分配,通过代码编写实现其所需的功能,完善程序项目总体流程菜单,最后总体调试程序项目功能。
  2. 熟悉掌握Dev C++编程环境,学会使用调试功能找到程序代码运行后出现的问题,并通过调试提示来解决问题。
  3. 学会通过百度、书籍资料对不了解的知识进行搜索,并学会应用。
  • 项目内容
  1. 实现对电子地图管理系统二进制文件的读取、排序、检索和更新功能。
  2. 将二进制文件读取后,高低字节转换存入数组中,并写入十进制文件。
  3. 读取转换后的十进制文件,并且采用冒泡排序法对十进制文件里的数据进行排序,并写入新的十进制文件。
  4. 采用二分查找、顺序查找方法对道路信息中的道路名字、道路编号、道路岔路数、道路番号进行检索。
  5. 把步骤三中排序好的文件转换成二进制文件,并且创建一个新的二进制文件放入。
  • 软件设计
  • 整体设计:

图1 实验项目的整体程序流程图

实验程序的结构如图1所示,图中方框表示函数,方框中指出函数名,箭头方向表示函数间的调用关系。

包含如下函数:

·Menu():菜单(界面),设计本项目的主画面,列出本项目所有功能。

·ReadFile():读取功能,读取二进制文件,并将数据放入文本文件中。

·Sort(DataInfo a[], int N):排序功能,对已加载成功的二进制文件排序。

·WriteFile():将排序好的数据写入文本文件中。

·Search():检索功能,对已排序的数据进行检索。

·BinSearch1(DataInfo R[],int n,int k):使用二分查找法对LinkID进行查找。

·SeqSearch1(DataInfo R[],int n,char k[]):使用顺序查找法对道路名称进行查找。

·SeqSearch2(DataInfo R[],int n,int k):使用顺序查找法对岔路数进行查找。

·SeqSearch3(DataInfo R[],int n,int k):使用顺序查找法对番号进行查找。

·gengxin():更新功能,对已排序好的文件替换原来的文件。

  • 功能设计
  1. 读取二进制文件:

图2 读取二进制文件流程图

如图2所示:

①文件打开:利用fopen打开二进制文件,并用“rb”和“w+”进行文件读取与编写。

②高低字节转换:将读取好的数据进行高低字节转换,利用按位或和按位与将十六进制顺序进行移位。

③循环放入数组、写入文件:while语句表示就是只要从文件里读取数据块成功,就继续执行读取操作直到文件末尾或读取错误。在循环语句中,从dataSize=0开始,先读取一条道路信息,对道路信息进行高低字节反转,再将此信息存入结构体中,并且写入txt文件中,检验到文件尚未读取完毕,继续操作,读取又一条道路信息直至文件读取完毕或读取错误。

关键代码及说明:

图3 读取部分关键代码1

如图3所示,用fread从fp1文件中读写一个字节数为4的数据,并对读取的数据进行二进制的高低字节反转。

图4 读取部分关键代码2

如图4所示,不同的CPU采用的端处理方式可能不同,在大端的处理器处理在小端上存储的数据,则需要对读取的数据进行反转排列。这里采取的是整形的字节转换,以“#define M_CHG_INT16(x) ((x>>8)|(x<<8))”为例子,这里为2个字节的反转,以1900为示例,当将19往右移2位即二进制的8位后,补零后得到0019,实现了反转。

图5 读取部分关键代码3

如图5所示,此代码先是通过fseek将文件位置向后移动4个字节,略去“1=”的部分,再开始用fread读取道路名称;strcpy(s1,s2); strcpy函数的意思是:把字符串s2拷贝到s1中,连同字符串结束标志也一同拷贝。在此代码中表示将字符串data[dataSize].CrossName拷贝到CrossName中。

  1. 排序:

图6 排序部分流程图

如图6所示,使用Sort函数实现排序功能,所用的排序方法为冒泡排序法。

实现过程是:

  1. 首先让用户先选择对什么道路信息进行排序。
  2. 选择1就对LinkID排序,选择2就对Class排序,选择3就对   CrossWay排序,选择0就返回主菜单。
  3. 假设选择1,进入冒泡排序,就能得到对LinkID排序的文件。

关键代码及说明:

图7 排序部分关键代码1

本项目所用的排序方法为冒泡排序法,是一种典型的交换排序方法,其基本思想是通过无序区中相邻元素关键词间的比较和位置的交换使关键词最小的元素如气泡一般逐渐往上“漂浮”直至“水面”。

如图7所示,以其中一个冒泡排序为例,从数组的第一个元素开始,即数组下标为0,外层循环控制行,使外层执行次数为MaxSize(数组元素个数)减1次;内层循环控制行,使内层每次比较次数为MaxSize(数组元素个数)减1再减执行次数;然后再对两个相邻的元素进行比较,数组元素比后一个元素大的要进行交换,使较大的元素往后排;经过一趟冒泡排序之后最大的元素在最后面;接着剩下的元素继续循环,交换位置,直到所有元素都有序为止。

图8 排序部分关键代码2

如图8所示,为将排序好的数据放入文本文件中的代码,运用到C语言文件操作。最主要的就是使用while循环将已排序好的道路信息一条条fprintf写入文件中,一直循环到63538条信息全部写入文件中。

  1. 检索:
  1. 二分查找:如下图9所示

图9 二分查找流程图

  1. 顺序查找:

从n个元素的数组第一个元素开始与要查找的元素进行对比。若R[i]个元素与目标元素相等,则返回i+1,表示该元素在第i+1个;若i<=n,则错误,数组中没有这个元素。

  1. 关键代码及说明:

1)

图10 检索部分关键代码1

如图10所示,大于5条的信息将输出结构写入文档,该程序中对岔路数和Class番号的检索采用的是顺序查找的算法,为了实现结果写入文档,将遍历的循环与写入文档结合。

图11 检索部分关键代码2

如图11所示,利用LinkID的唯一性以及是数字的特征,对LinkID采用相比于顺序查找性能更好的二分查找,无需对所有顺序进行遍历。

  1. 更新

表1更新代码一步步优化过程

版本1:

初始先建立更新的文本文件Sort.txt,再读取文件到结构体的数组之中,再对数组进行二进制写进原始文件进行覆盖。

版本2:

不建立使用更新的文本文件Sort.txt,可以使用排好序的结构体数组data作为实参代回形参结构体b[]。

版本3:

不建立使用更新的文本文件Sort.txt,直接使用身为全局变量的结构体数组data,此时的data进行过排序功能操作后覆盖原始数组,变成了排好序的结构体数组。

如表1所示,优化后,最后使用的整个更新程序流程图如下图12:

图12 优化后的整个更新流程图及部分重要代码

  • 测试分析
  • 功能测试:
  1. 整体界面

图13 地图整体界面

本项目的整体画面设计如图13所示,界面显示为本项目的主画面,其中最上方为项目的名称和创建时间以及创建者等相关项目的信息,如同Windows项目的帮助一样。

以顺号的形式列出了本项目的所有的功能,有读取文件、排序、检索、更新、退出等功能。

  1. 读取界面

图14 文件读取界面1

如图14所示,当“请选择”项目输入数字1的时候,如果文件读取成功将会有消息提示,并重复显示服务的种类。

对生成的文件的输出位置要有明确的说明,以作为其它功能的应用源文件。

对以前的操作记录以保留的形式进行滚动地进行保留,加载文件成功以后一定要返回到所有服务种类的项目界面。

图15 文件读取界面2

如图15所示,如果源文件不存在会有提示。

  1. 排序界面

图16 排序界面1

如图16所示,当“请选择”项目输入数字2的时候,进入排序功能,会提示选择道路排序方式,让用户选择对哪种道路信息进行排序,并重复显示服务的种类。

图17 排序界面2

如图17所示,当“请选择”项目输入数字1的时候,用冒泡排序法对LinkID排序,并告诉用户正在排序中,排序成功后,放入文件中,并提示用户文件输出位置。当用户想退出排序界面时,可选择数字0退出到所有服务种类的项目界面。

  1. 检索界面

图18 检索界面1

如图18所示,当“请选择”项目输入数字3的时候,进入检索功能,可选择4种检索方式,如果想退出检索界面,可输入数字0返回到所有服务种类的项目界面。

图19 检索界面2

如图19所示,输入数字1时,指定LinkID检索,提示用户输入要查找的LinkID,例如输入1208,即可得到相应道路信息。当用户还需要指定岔路数检索时,可继续输入数字进行检索。

图20 检索界面3

如图20所示,输入数字2时,指定岔路数检索,用户输入想要检索的岔路数,当检索结果大于5时,放入文件中,并说明输出文件位置。

查找成功后,返回到所有服务种类项目界面。

图21 检索界面4

如图21所示,对于检索输入的关键字没有检索到要有提示。并返回到检索画面。

  1. 更新界面

图22 更新界面

如图22所示,是对已排序好的二进制文件替换原来的文件,如果出现错误会作出提示,一旦成功后源文件就是新文件了。

  • 测试过程遇到的问题及解决办法

图23 测试问题1

如图23所示,

(1)问题:道路名称输出时会有“1=”,并且读取的道路名称部分有误。

(2)分析:运行后,我们发现道路名称会多个“1=”,通过询问老师,我们知道是读取反转后自带的,所以想到了将“1=”删去的方法,但是代码实现不了,只能转向先用strlen算出“1=”字节数,然后用fseek从当前位置往后读4个字节数;我们发现得到的有误的道路名称往往和上一个道路名称相同,重新测试代码,发现是没有判断道路尺寸大于12的情况,导致将上一个数组中的道路名称继续复制下

(3)解决:最后加上了if语句判断道路尺寸是否大于12,并且加了个fseek语句将文件指针往后移4个字节数,并且fread语句中读取的字节数再减去4。

图24 测试问题2

如图24所示,

(1)问题:排序完毕后将结果放入文件中,看到从LinkID为10开始,    后面的道路信息错位。

(2)分析:各个数据有的是2个字节,有的是4个字节,你可以 尝试指定每个变量输出的占位长度,比如,%10d,指的是占10个字节,
应该说是占用的字符数,10d占10个字符宽度。

(3)解决:将fprintf(fp2, "LinkID=%d\t\t",data[dataSize].LinkID)里的%d改为%10d,数据就不会错位了。

(1)问题:想用一个排序函数分别对各种道路信息进行排序,但是不知道怎么操作。

(2)解决: 一个冒泡排序函数中,根据不同字段来排的话,可以进入此函数时 ,让用户选择一下想按什么信息进行排序,那么先printf出可选择什么信息进行排序,再用switch 实现选择功能,在对应位置完成相应成员的排序 ,分3个部分,对LinkID、Class、CrossWay 分别冒泡排序。

图25 测试问题4.1

图26 测试问题4.2

如图25,26所示

(1)问题:无法进入Search()。

(2)分析:在Menu()函数中,调用Search()语句前后进行输出,发现都可以正常输出,所以Search函数没有发生错误使函数停止运行。在Search函数中检查,猜测可能是没有进入该函数中的循环结构,在该循环中写入输出语句,发现没有输出,因此肯定是进入while的条件有错。
 (3)解决:最后把“while(r=0)”改成“while(r==0)”即可。错误的原因是将判断语句写成了赋值语句。

图27 测试问题5.1

图28 测试问题5.2

如图27,28所示,

(1)问题:对LinkID检索显示在搜索中,很长时间没有输出。

(2)分析:猜测是在LinkID检索的功能函数中的循环写错,导致进入了死循环。

(3)解决:检查中发现,有一条语句“mid=(high+low)/2;”没有写入循环。

图29 测试问题6

如图29所示,

(1)问题:对岔路数搜索,搜索的信息是正确的,但出现了刷屏且岔路数相同的信息又多条,此处只输出了多条相同的信息。

(2)分析:猜测是对岔路数进行搜索的函数出现了问题,刷屏猜测是循环输出搜索到的第一条符合的信息。

(3)解决:不能用二分法输出多条信息,因此修改为顺序查找。

图30 测试问题7

如图30所示,

  1. 问题:错误处代码,无论对道路名称查找输入“1=104国道”或“104国道”都会显示输出错误,无法找到数据。
  2. 分析:可能是对输入格式有要求,如中间有空格,从十进制文件中直接复制出其中一个道路名称,仍会报错,所以排除输出的问题。可能是对比的语句出现问题,最后发现字符串无法直接用“==”进行判断。
  3. 解决:调用函数strcmp()对比字符串,若strcmp==0则表示字符串相同。
  1. 问题:多次测试后exe出现提示:process exited with return value 3221225477。
  2. 分析: 3221225477 (0xC0000005): 访问越界,一般是读或写了指针指向的内存;3221225725 (0xC00000FD): 堆栈溢出,一般是无穷递归造成的;3221225620 (0xC0000094): 除0错误,一般发生在整型数据除了0的时候。经调试验证,为第一种错误。程序访问的文件GBTL.tat已经被更新过了,无法再次再进行程序。

(3)解决:应该备份一份未更新的GBTL.tat文件,方便每次调试的使用

图31 测试问题9

  1. 问题:不知道是否真的更新后的二进制文件是我们想要的文件,所以利用二进制读取文件转化成十进制,验证是否与排序好的十进制txt相同,但是每次依然出现提示:exe出现提示:process exited with return value 3221225477.
  2. 分析:不能直接使用功能1读取文件来验证,因为更新之前读取过一遍文件,高低反转过了,不能再利用功能1读取文件再来高低反转一次,否则便会出现错误。
  3. 解决:验证是否更新完成,应该重新写个没有高低反转,直接读取后十进制输出的程序来验证,如图31所示。
  • 性能测试
  1. 排序

图32 排序性能测试

如图32所示,一开始用的是直接插入法,但是由于这个排序方法运行比较慢,就改用了冒泡排序法。

快速排序法会比以上两种排序方法都快,但是由于涉及的代码较复杂,所以没有使用。

  1. 检索

图33 检索性能测试1

图34 检索性能测试2

如图33所示,是二分查找的代码,如图34为顺序查找的代码。可见,在数据有序的情况下,二分查找程序的时间复杂度是O(log2(n)),而顺序查找的是时间复杂度为O(n)。由于O(n)>O(log2(n)),可是二分查找的性能高于顺序查找。

图35 检索性能测试3

但如果数据是无序的,在用二分查找的前提下需进行排序,将排序和二分法与顺序查找的程序所用的运行时间对比,发现,在一定数量的数据下,排序加上二分法所运行的时间会比顺序查找多很多,如图35所示,是利用clock(),对两个算法的运行时间的数据记录。

  • 总结与展望

通过此次实训,我们小组意识到团队合作的重要性,分配好模块后可以大大减小压力,并且可以互相帮助解决问题;再者是代码实现过程中遇到了很多问题,我们通过找寻大量资料或者询问老师一步步完成了代码的编写;最后是测试阶段,期间遇到了很多问题,比如更新文件想要验证文件是否正确时忽略了大小端区别,导致误以为文件更新错误,走了很多弯路,所以其实测试时应该从多个方面考虑,回到最开始。

同时,我们意识到了自己的不足,针对这些不足,我们会一步步改进,并且多加学习和练习,加强编写代码能力,相信我们的解决问题能力越来越强。

应用程序开发——电子地图管理系统相关推荐

  1. 学校智慧校园平台管理系统小程序开发制作

    学校智慧校园平台管理系统小程序开发制作 智慧校园服务的蓝海市场正在等待开发的状态中,而小程序恰好是一体化校园平台抢占这个市场的最佳方式. 学校校园平台小程序提供在校大学生和老师校园智慧服务的小程序应用 ...

  2. 开发小程序以及后台管理系统攥淘宝佣金

    开发小程序以及后台管理系统,私聊了解详情. 带徒对接淘宝赚取佣金,有想法可以沟通

  3. 全新PHP程序开发在线工单管理系统源码,售后工单系统

    源码介绍 很多会员需要的在线工单系统,客户售后服务系统,php写的非常不错! 项目说明: 1.1 :客户管理:可实现对职员的管理,可添加职员,并对不同角色的职员分别进行授权及停用操作. 1.2 :客服 ...

  4. 小程序源码 租房管理系统_如何通过租房小程序开发快速引流

    租房市场在整个房产市场占据了极大一部分市场份额,而随着租售同权政策的提出.房价的不断提升,租房市场份额将进一步扩大. 合肥小程序开发智速新媒体公司 传统的租房方式不管是出租方还是租房客户,彼此之间的消 ...

  5. 基于ssm框架—微信小程序开发的会议管理系统

    本系统是基于ssm架构(Spring+SpringMVC+MyBatis)开发的后台管理会议系统,系统以Java作为编程语言,采用Mysql数据库作为后台数据库.它是基于Browser/Server结 ...

  6. 毕业设计-基于微信小程序平台开发样品管理系统

    目录 前言 课题背景与简介 实现设计思路 一.低压电器样品管理现状与难点 二.样品管理程序设计 三.微信小程序开发 四.服务器与数据库搭建 五.总结 实现效果样例 更多帮助 前言

  7. 通讯录管理系统程序开发

    用数据库实现通讯录管理,主要功能: 1.分组管理 设计分组方案(如分组类型包括家庭.朋友.同学等),设计创建分组数据表,实现对分组的增删查改. 2.通讯录管理 设通讯录信息主要包括:姓名.性别.单位. ...

  8. python编程案例教程答案-Python程序开发案例教程

    内容简介 Python是近年来最流行的编程语言之一,其清晰的语法和可读性使其成为初学者的完美编码语言,并且深受编程人员的喜好和追捧. 本书从入门者角度出发,以简洁有趣.通俗易懂的语言讲解了全新的Pyt ...

  9. python实现宿舍管理系统_基于PYTHON微信小程序的病历管理系统的设计与实现

    好程序设计擅长JAVA(SSM,SSH,SPRINGBOOT).PYTHON(DJANGO/FLASK).THINKPHP.C#.安卓.微信小程序.MYSQL.SQLSERVER等,欢迎咨询 今天记录 ...

最新文章

  1. Plugin with id 'com.novoda.bintray-release' not found的解决方法
  2. 单独使用 EHCache
  3. java ajax无刷分页_asp.net+ajax+json来实现无刷新分页功能
  4. Distimo发布新SDK 帮助开发者跟踪应用下载转换率
  5. 永久白嫖!发现官方漏洞,希望不要被封杀!
  6. C++ 面向对象(三)异常 :异常概念、异常的匹配规则、异常安全、异常体系
  7. JDK安装与配置(Windows 7系统)
  8. Makefile札记
  9. 剑指offer面试题[23]-从上往下打印二叉树(按层序打印)
  10. LSH︱python实现局部敏感哈希——LSHash(二)
  11. 每日三道前端面试题--vue 第一弹
  12. Unity中资源打包成Assetsbundle的资料整理
  13. java 与 c# 3des 加解密
  14. C/C++编程笔记:C语言编程知识要点总结!大一C语言知识点(全)
  15. 培根密码(Bacon)——python解密
  16. DNS 技术标准综述
  17. 信息安全软考—— 第五章 物理与环境安全技术 学习笔记
  18. 一文告诉你怎样“火起来”
  19. 巴西游戏出海攻略,优质游戏出海市场
  20. 浅谈【CSS】渐变背景(background-image)以及基础用法

热门文章

  1. R语言使用runif函数生成符合均匀分布的随机数、使用plot函数可视化符合均匀分布的随机数(Uniform Distribution)
  2. Java项目中使用spring (annotation)
  3. 【大一立项】ROS服务机器人-结题报告
  4. python中字典合并方法
  5. 无法删除的软件,如何删除
  6. 【OpenCV】 车辆识别 运动目标检测
  7. python气象数据可视化学习记录1——基于ERA5数据画风场和海平面气压填色叠加图
  8. 将视觉深度学习模型应用于非视觉领域
  9. 计算机图形学之空间坐标变化之三维图形观察及变换
  10. 勤哲 mysql 2005_勤哲Excel服务器-学习与下载园地