




免费预览已结束,剩余36页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本 科 毕 业 论 文 基于C语言的文本编辑器功能响应模块,部分编辑功能模块和显示功能模块A Text Editor Based on C Programming LanguageFunction Directing, Editing and Display Module姓 名:学 号:学院:软件学院系:软件工程专 业:软件工程年 级:指导教师: 年 月摘要文本编辑器是用来编辑文本的工具,它被广泛地集成在各种操作系统中。它不仅仅是一个操作系统提供给用户的最基本常用软件之一,其实文本编辑器对于任何操作系统本身也是具有非常重要意义的。该文所要论述的是一个具有不同思维模式的文本编辑器,它是基于构建在Windows操作系统之上的DOS环境并利用C语言加以实现的。考虑到DOS平台对于内存使用的限制,设计中采取逻辑文件页这样的概念来解决这样的问题,同时也针对文本编辑器逻辑文件页的特点自定义了文件存储的格式。逻辑文件页这样的概念的提出使得内存使用得到了优化。因为在编辑文本的某一个时刻只会集中在文件的某个区域,也就是说其他部分文本此时其实是可以保存在磁盘上。如果再能够保证在操作这个特定区域的时候,相应部分的文本处于内存中那么它就可以正常的工作而不会发生错误,从而内存得到很大节省。这也就意味着在加载文件的时候没有必要一次性加载了,这些全都得益于逻辑文件页的出现以及由它而定义的文件存储格式。除了逻辑上的革新之外,操作界面也变得更加人性化。众所周知,DOS下的界面是远远不及现在的图形操作界面那么人性化和可操作的。该设计中引入了很多快捷键也加入了更多的图形界面,但是始终还是没有加入鼠标的支持。考虑到问题本身已经得到陈述而且不考虑鼠标支持可以大大降低逻辑复杂性,所以最终也就没有加入这个高级功能。总的来说,最终的设计使得即使面对大文件的读写的时候也会表现优良,而且也会节省内存的使用。本文是对上述设计思想的详细的论述,同时文章也会对主要处理流程加以详细的逻辑和性能分析。关键词:文本编辑器;逻辑文件页;虚拟机AbstractThe text editor, as the name goes, is a tool designed for text editing, it has been incorporated into all kinds of Operating Systems (OS). Not only is it the most fundamental software provided by OS to the users, but the editor is also very crucial to the OS itself.This paper will discuss the kind of editor with a unique thought behind which is implemented using C based on the virtual machine for DOS under Windows environment. Given the limitation of memory use for DOS, a method named logical file page is devised to tackle this problem. In the mean time, we also defined our own file format for storage according to this special scheme. The proposal to use logical file page has made memory use more efficient. Since the focus on the file will be limited to a specific area while editing, that is to say, other parts can actually remain on the disk. If it is guaranteed that the part being operated on resides in memory, errors would not arise due to memory faults. As a result, the memory use has been minimized in a sense. At the same time, this also means that it is not imperative to load the whole file immediately and all of these accredit from that concept, logical file page.Besides logical innovations, the GUI has become more humane as well. The GUI of DOS is incomparable with those of mordern OS. So, in this design, you will observe that more hot keys and some graphics as well. But still the system does not support mouse. Considering that the aim to demonstrate the idea of this editor is reached and it will be much more easier without concerning mouse, this extra function is abandoned for convinience.To conclude, this design will still lead to a good performance even if it is confronted with large text files, and the memory use will also be saved. This paper is a summary for all the ideas mentioned above and it will exlpore more deeply on some critical procedures by analysing the details. Key words: text editor; logical file page; virtual machine.目录第1章 绪论11.1 论文背景11.2 论文结构组织1第2章 系统的设计32.1 开发平台32.2 平台选择带来的挑战32.3 模块的划分32.4 模块之间的关系5第3 章 系统的实现63.1 功能响应模块63.1.1 键盘信息结构体63.1.2 主循环73.2 编辑功能模块73.2.1 逻辑文件页结构73.2.2 剪切板结构93.2.3 编辑文本操作103.3 显示功能模块133.4 文件操作模块143.5 菜单功能模块15第4章 系统性能及测试174.1 系统性能及运行结果174.1.1 部分逻辑操作的效率174.1.2 部分刷新操作的效率174.1.3 程序的运行结果184.2 系统的测试184.2.1 测试工程的建立184.2.2 单元测试部分194.2.3 集成测试部分194.2.4 系统测试部分19第5章 总结20致谢语21参考文献22ContentsChapter 1 Preface11.1 Background11.2 Structure of This Thesis1Chapter 2 System Design32.1 Developing Platform32.2 Chanllenge Arised With Choice of Platform32.3 Division of Modules32.4 Relationships Between Modules5Chapter 3 System Implementation63.1 Function Directing Module63.1.1 Keyboard Information63.1.2 Main Loop73.2 Editing Module73.2.1 Logical File Page73.2.2 ClipBoard93.2.3 Operations of Editing103.3 Display Module133.4 File Module143.5 Menu Module15Chapter 4 System Performance and Testing174.1 System Performance and Running Outcome174.1.1 Efficiency of Some Logical Operations174.1.2 Efficiency of Some Refresh Operations174.1.3 Running Outcome of System184.2 Testing184.2.1 Establishment of Test Project184.2.2 Unit Test194.2.3 Integration Test194.2.4 System Test19Chapter 5 Summary20Acknowledgement21References22基于C语言的简单文本编辑器第1章 绪论1.1 论文背景在科学技术日新月异的今天,各行各业都经历着前所未有的变化。在信息科学与技术领域,同样的事情也正在发生着。现代操作系统、编译器、数据库系统以及网络等等诸多学科的发展为这个学科带来了革命性的进步。例如:现代操作系统的产生不仅仅大大提高了系统的效率,它也为程序开发人员提供了更多的便利。正是由于这样,当今的技术人员在开发新软件的时候,他们会更多的关注软件的架构以及业务逻辑本身。但也正是由于这样一系列的缘故,很多经典的知识就像被披上了一层神秘的面纱对大多数人是不可见的。例如:大家都知道现代操作系统采用虚拟内存的机制完美解决了内存使用相关的一系列问题,然而人们却很少或者是没有机会去更加深入地接触这部分的知识。一直以来,底层的一些知识总是对人们有特殊的吸引力,因为它融合了诸多方面的知识,而且更是体现着计算机科学这个学科的本质特征。所以一开始编译器是作为候选的,然而考虑到编译器内在的复杂性和相对上时间和精力的不足,团队最终将任务确定为研究一个自主设计的文本编辑器。对此一个计算机科学家也曾经表示,文本编辑器其实对最终实现操作系统也具有重要意义。这个文本编辑器的不同之处在于它本身将会具有一定得学术指导意义,同时它也将起到全面考察学生对思考问题和解决问题能力的作用。具体来说,实现人员将会自己去提供它所需要的一切核心组件。例如:底层图形界面,逻辑部分需要的数据结构的支持。1.2 论文结构组织本文根据文本编辑器设计和实现过程中遇到的重点和难点而作,具体介绍其中设计的依据以及实现过程中的相关处理。第1章 本文的概论:主要介绍相关背景等信息。第2章 系统的设计:主要介绍系统构建的平台、主体模块的划分以及各个模块之间的协调情况等。第3章 系统的实现:主要详细的介绍相应模块具体的处理流程。第4章 系统性能及测试:主要分析核心程序块的效率同时对系统测试做出说明第5章 总结 接下来文章就是按照上面部署的顺序进行陈述的。第2章 系统的设计2.1 开发平台考虑到论文的目的以及要开展的工作的性质,DOS系统下的Turboc 2.0平台将被作为主要开发工具,开发语言为C语言。2.2 平台选择带来的挑战其实平台选择所带来的问题也正是论文中的亮点,它自身特点会体现该文章提出的为解决既定问题而做出的特殊的设计。正如背景中指出的那样,我们将会为该文所阐述的编辑器直接提供底层需要的一切数据结构和操作。就一个文本编辑器而言,它可以是非常复杂同时也可以是非常简单的。正是由于选择了DOS作为我们的开发平台、C语言作为我们的实现语言,这也就预示着工作量的巨大。人们都知道传统的DOS系统对应用程序能够占用的内存是有一个上限的,为此以往很多时候程序员需要自己去管理内存上的使用。例如:自己去负责内存的换进换出、自己负责程序模块的加载等。在该文的设计中,程序员将会去负责编辑时某些文本块的加载和写回。这也是整个系统众多闪光点之间的一个。2.3 模块的划分从整体来看,设计整体上可以分为如下几个方面:(1)基础数据结构部分1:单链表模版,双链表模版,堆栈,键盘信息结构体,剪切板,页结构体,文本行。 (2)菜单功能部分:加载,新建,保存,另存为等。 (3)编辑功能部分:各个键的响应等。 (4)显示功能部分:菜单,各种类型的对话框显示等,同时显示功能也包括对应着编辑和菜单功能的部分,这也是因为一旦使用者做出操作之后,就可能对视图造成变动。 (5)功能响应模块:根据来自键盘的消息将具体程序控制转接到相应 的子模块。 (6)文件操作部分:临时文件的管理,文件的保存和读取等等操作。 (7)初始化模块:程序中必要的一些数据的初始化工作。 (8)资源回收模块:程序结束后需要清理的一些资源使用。接下来就按照上面的划分对各个模块做一个更加具体的说明,介绍的顺序会与kernel文件夹中主要源文件和其功能模块先挂钩。我涉及的部分模块:(1) start.c进入循环,不断接受来自键盘的信息,对功能键和非功能键给以响应。更加不同的键,去调用其他具体各个模块中的具体功能。(2) init.c 包含必要的一些初始化操作函数,对程序中所需的数据进行设置(3) finalize.c 包含针对不同数据结构进行资源释放的操作(4) foperate.c 包含了对于文件的具体操作,这里面的所有操作是供其他上层模块来调用的。(5) clip.c 包含了对于支持三种不同类型剪切板的支持所必须得操作函数(6) page.c 包含了所有逻辑文件页所有必须得操作(7) edit.c 包含了对于各种键盘功能键和非功能键的具体功能在逻辑上的响应。(8) updatev.c 这个文件是对应着edit.c的,它包含了所有对于edit.c编辑过程的后续操作。具体是对edit.c中操作引起的视图变化加以显示更新。(9) display.c 包含了具体的对屏幕操作的函数,这些函数主要供上层视图更新的操作调用。(10) menu.c 包含了一些对菜单显示的具体操作。(11) menuacts.c 包含了所有对菜单功能的响应函数。其他成员负责的模块,但是具体的功能在这里将不做具体的描述。它们所对应的代码源文件如下:edit.,updatev.c,menuacts.c,dialog.c,listnode.c,list.c,dnode.c,dlist.c,stack.c,textline.c,position.c,tmpfile.c。2.4 模块之间的关系图 2-1:模块联系图该图展示的是总体设计中各个主要模块之间的相互联系,这个联系表示一个模块功能的完成需要哪几个模块的协作。同时该图也透露了整体的流程处理:首先完成所需数据的初始化,紧接着进入键盘信息的监听。之后提取键盘信息再依据信息进行匹配,进而进入相应处理的子模块。在逻辑处理完成之后再按照逻辑数据对视图进行更新。在整个过程中,如果发现键盘信息表示退出程序,则回收相应资源并终止程序的运行。第3 章 系统的实现3.1 功能响应模块3.1.1 键盘信息结构体显然系统的处理流程都是和键盘信息有关的,因为无论是编辑的响应还是功能的调用都是来自于键盘的特定键。为了方便处理这个方面的信息,设计将所需要的信息放在一个结构体内。typedef structint key1, key2;int isinson, isshifton, iscapson, isalton, isctrlon;KeyBoard;相应的操作函数:extern void getkeyvalues( KeyBoard * );extern void getkeyinfo( KeyBoard * );extern int iskeyasc( KeyBoard *, int ); 成员变量key1和key2的更多信息:key1是一个16位的二进制数,它可以通过系统函数bioskey(0)得到,包括两部分值。当按下一个普通键时,它的低8位数存放该字符的ASCII码;对于特殊键(如方向键、F1F12等等),低8位为0,高8位字节存放该键的扫描码。key2是一个16位的二进制数,它可以通过系统函数bioskey(2)得到,表示Shift、Ctrl、Alt、ScrollLock、NumLock、CapsLock、Insert键的状态。各键状态存放在返回值的低8位字节中。关于该结构体的方法:void getkeyvalues( KeyBoard * ); 该函数捕获键盘状态,并根据硬件返回的信息对key1和key2进行赋值。void getkeyinfo( KeyBoard * ); 根据参数中键盘结构体的信息,计算出特殊键的状态。int iskeyasc( KeyBoard *, int ); 返回此次按键是否是ASC码,如果是就返回1,否则返回0;3.1.2 主循环伪代码3-1:当程序还没有退出执行利用上述键盘信息结构体的函数进行操作;如果此时菜单被选中根据被选中菜单进行功能调用否则对编辑做出必要的响应退出程序 上面这段伪代码是程序主循环的处理过程。从上面的伪代码大家可以看出,在主循环中设计区别了两种状况。一种就是:当有菜单的情况。显然,当菜单处理下拉状态的时候enter,up,down等键是具有和没有菜单时的情况是不一样的。3.2 编辑功能模块3.2.1 逻辑文件页结构typedef structint status;List texts;PageContent;typedef struct pageint flag;int found;int linecount;int startline, endline;PageContent *content;long offset;FILE *fp;Page;相关的操作函数:extern int pageinit( Page *, int found, int startline, int endline, PageContent * );extern Page* getpagewithtextline( int, int, TextLine* );extern DoubleNode* getpagenodewithindex( int );extern int addlineonpage( Page *, TextLine * );extern int insertlineonpage( Page *, int line, TextLine * );extern void dellineonpage( Page *, int line );extern void dellinesonpage( Page*, int, int );extern int addcharonpage( Page *, int, int, char );extern void delcharonpage( Page *, int, int );extern void replacecharonpage( Page *, int, int, char );extern char getcharonpage( Page *, int, int );extern void deactivatepage( Page * );extern int activatepage( Page * );extern void mergepage( DoubleNode *, DoubleNode * );extern void splitpage( DoubleNode * );extern void reorganizepage( DoubleNode* );extern void seperatepageat( DoubleNode*, int );结构体PageContent表示这个页中的具体内容,也正是这个区域的内容会被写进和写出。其成员变量分别表示:该页的状态和一个保存文本行的链表。可以得出,这个结构体是整个Page中最占用内存的一个结构。成员变量分别表示(按照顺序):对应这个页的临时文件是否有内容、这个页当前是否驻留内存、这个页文本行的行数、该页在全文本文件中的行数范围上限和下限、页内容的指针、该页在原文件中保存的离文件头的起始偏移量、该页所对应的临时文件的文件指针。对于页的一些说明:(1) 页的大小:每个页的默认大小是一个定值(设计中定义为了一个宏常量)。但是这并不意味着每个页的长度是固定的,这也是因为使用者会不断对某个页进行编辑的结果。所以设计中对其设置了上限和下限,允许一个页的长度在这个范围内进行变动。然而,这样也就引出了其他的问题,例如:一个也可能会变得太大或者太小。为了解决页大小的问题,设计特别定制了一些函数,对一些不符合页大小的页进行整合。具体就是对于也得分裂和合并以及整合相连页的操作。(2) 页换进换出的时机:设计在全局范围内设置了两个变量,它们分别是startrow和endrow来跟踪屏幕当前显示的内容在原文本文件中的行范围。显然,如果一个页和这个区间没有任何重叠的话,那也就意味着这个页此时可以被换回到磁盘。否则也就意味着这个页的部分是需要被显示的,也就必须驻留在内存中。(3) 页行范围的改变:在编辑过程中,某些操作是会引起行范围变化的。例如:删除,回车插入行等。所以,实现中会对行范围进行更新。这个范围的变化是什么重要的,因为判断一个页是否有必要驻留内存是和这个有关的。核心的操作:extern void deactivatepage( Page * ); 将一个也按照固定的格式写回该页所对应的临时文件extern int activatepage( Page * ); 将页从它所对应的临时文件加载入内存extern void mergepage( DoubleNode *, DoubleNode * );将两个邻接的两个叶结点进行整合extern void splitpage( DoubleNode * );将这个页节点中逻辑页进行适当的拆分extern void reorganizepage( DoubleNode* );对一个叶结点和邻接的进行整合以调整到适合的大小正是基于这样的逻辑文本页的概念,设计中将其用一个双链表的结构来表示被编辑的目标文件。图 3-1:文件页链表示意图正是由于这样的设计,系统就可以不用全部加载整个文件。同时,使用者现在操作的对象从针对原先的文件发展到了针对了焦点所在的逻辑文件页。这也就意味着,实现人员在每次操作文件页的时候,必须保证相应的文件页是在内存中的,否则将会出现程序内存访问出错。3.2.2 剪切板结构设计中自定义的剪切板基本有两种类型:一个是仅仅包含单行文本的剪切板,另外一个就是包含多行文本的剪切板。typedef unionTextLine *textline;int linecount;ClipContent;这个结构体表示的是这个剪切板中的内容,如果是单行,内容保存在Textline*指针指向的内存区域。否则linecount指示有多少行,然后文本内容保存在fp文件指针对应的文件中,这也是处于对内存的考虑。试想如果剪切板中包含了全文件内容,如果不将这个内容保存到文件,那此时其他的设计都付之东流。因为剪切板的驻留就相当于让这个文件驻留内存,所以做出这样设计的考虑是完全明智的。typedef structenum ClipType type;ClipContent content;FILE *fp;ClipBoard; 相关的操作函数:extern void clipboardinit( ClipBoard * );extern void clipboardinitsingleline( ClipBoard *, enum ClipType, TextLine * );extern void clipboardinitmultiline( ClipBoard *, enum ClipType );extern void disposeclipboard( ClipBoard * );extern void setclipwithin( ClipBoard*, int, int );extern TextLine* getnextline( ClipBoard* );extern DoubleList* getclipcontent( ClipBoard*, int, int* );此时大家可以观察到,对于ClipBoard的设置其实是采取了一种类似Page的策略:将剪切板隔离出剪切版内容这个结构体这个概念。重要的函数:extern void clipboardinitsingleline(ClipBoard *,enum ClipType,TextLine * ); 这个函数对单行文本类型的剪切板进行初始化。extern void clipboardinitmultiline( ClipBoard *, enum ClipType );extern void setclipwithin( ClipBoard*, int, int );上面两个函数是操作多行文本剪切板的必要两步操作,一是初始化二是对剪切板进行内容上的设置。extern DoubleList* getclipcontent( ClipBoard*, int, int* );这个函数仅仅在剪切板内容类型为多行文本的时候才会被用到,它返回一个双向链表的头指针。这个双向链表的节点是一个一个逻辑文件页。它是在对剪切板内容进行分析之后然后根据剪切板的内容而返回的。3.2.3 编辑文本操作(1)Enter的功能响应:这是每个文本编辑器必须具备的功能,也就是插入新行。对于本编辑器而言,实现人员需要将页的因素考虑到这个过程中。伪代码3-2:新建一个新行;将原行中光标之后的所有字符拷贝入新行中;如果当前页是链表中最后一页,并且此时页中的行数达到了默认大小,此时就新建一个页,然后将此行插入页中;否则,直接将此行插入当前页中;重新调整各个页的信息,同时重新设置一些全局数据;必要页的换出和换进操作;如果当前页的大小达到需要调整的标准,调整当前页;否则程序退出并返回适当的值;上面这段伪代码反应了按下Enter后的处理流程的伪代码;(2)方向键的功能响应:方向键起到了改变编辑位置的作用。同时结合shift键还可以起到选择文本的作用。下面,我将其分为两部分:上下和左右。因为,这两对操作的过程是不同的。伪代码3-3:如果当前行不是在第一行 如果光标在屏幕最上端, 必要的换进换出页操作; 定位当前行,同时取出上一行; 根据前后两行的信息,重新设置变量信息;程序退出并返回必要值;上面伪代码过程反应的是Up键按下的处理流程的伪代码;伪代码3-4:如果不是在当前行的末尾如果下一个字符为TAB, 跳跃一个定长; 否则,寻位到下个字符。程序退出并返回必要值;上面是Right键按下后的处理流程的伪代码;(3)复制的功能响应:当有文本被选中的时候,如果调用此项功能,将会将所要复制的文本设置到剪切板中去。具体的伪代码如下:伪代码3-5:判断选择文本的类型, 如果是单行文本类型 将文本取出,同时以它为参数初始化当行文本类型的剪切板。 否则 通过行范围,更加全局的文件页来初始化多行文本类型的剪切板。程序退出并返回必要值;以上就是复制处理流程的伪代码;(4)剪切的功能响应:剪切的大体操作和复制时差不多的。唯一不同的就是单单复制过程不会引起原文件的改动。然而,剪切了后在设置剪切板内容的同时,还要对原文件做出修改。伪代码3-6:判断选择文本的类型,如果是单行文本类型 将文本取出,同时以它为参数初始化当行文本类型的剪切板。 重新设置部分数据; 否则 通过行范围,更加全局的文件页来初始化多行文本类型的剪切板; 重新设置部分数据;程序退出并返回必要值;以上是剪切的处理流程的伪代码;(5)粘贴的功能响应:当剪切板中有内容的时候,使用者如果采用了粘贴操作,则取出剪切板中内容并将其加入到文件对应的文件页中去。在此,多行文本的操作和当行文本的功能实现是有着巨大不同点的。这也是由于对于它们设计的不同而决定的。伪代码3-7:判断粘贴板的类型,如果是单行文本, 将字符串插入到行中;否则如果是多行文本类型, 根据当前所在行号,将该逻辑页拆分为两个页。(当编辑行在逻辑页首或者页尾除外); 将剪切板返回的逻辑页链表插入到刚刚拆分的页的中间。对所涉及的页进行必要的整合操作; 更新相关页的信息,重新部分数据;退出程序并返回必要值;以上是粘贴的处理流程的伪代码;3.3 显示功能模块其实显示功能模块和编辑模块是相对应的。大家也应该注意到了,在编辑操作完成之后,都会有一个返回值。其实这个返回值正是为了下面紧接着的界面显示更新而专门设计的。不同的值对同一个类型操作的更新提示也是不一样的。例如:对于键right,如果没有触及显示边缘是不需要滚屏的,否则这个操作就是必须的。对于大部分操作,它们都有自己特定类型的刷新显示的机制和过程。但是它们也有共同点。比如:当滚屏的范围不确定的时候实现人员就需要根据逻辑数据对整个屏幕进行刷新。这样的操作不建议频繁使用,但是它们又是必须的。在这里,我对刷屏和刷行更新的函数做具体的介绍。在这之前,我首先要对四个参量做出说明,它们分别是:startrow,endrow,startcol,endcol;startrow表示屏幕最上端行位于实际文件中的行号;endrow表示屏幕最下端行位于实际文件中的行号;startcol表示屏幕最左端列号位于实际文件中的列号;endcol表示屏幕最有短列号位于实际文件中的列号;显然,有了这些变量的指示,加之dlistofpages的逻辑文件页的双向链表,屏幕上文本是可以被获取出来的。正是因为这样,实现人员才可以随心所欲的对需要部位进行更新,这样的操作也更有效率。伪代码3-8:将光标隐藏;定位到需要更新的地点;根据逻辑行的字符对这行进行刷新;将光标恢复;程序退出;以上是行更新操作流程的伪代码;伪代码3-9: 取出每一行,调用行刷新的函数; 程序退出; 以上是整屏幕更新操作流程的伪代码;另外在显示模块中处理了光标的显示和隐藏问题2,这点比较重要。如果有大范围内的屏幕刷新,但是此时光标是可见的,那么使用者将会看到较为明显的闪屏现象。此时其实可以在这样的操作开始之前先将光标显示屏蔽掉,之外再将其恢复。3.4 文件操作模块很自然,该文的设计中当然包含了文件的存储。鉴于特殊的逻辑页结构,设计的存储其实也是基于这个逻辑页的概念的。这样做的好处就是,它为在使用中打开文件时候不完全加载整个文件提供了可能。设计中所定义的文件存储格式如下:行的大小 行的容量行的内容总行数 逻辑页的个数页在文件中的起始位置 页的起始行 页的终止行.页结构信息在文件中的起始位置以上就是最终文件格式的存储。可以看出,在存储过程中会占用不少额外的空间。但是,这些信息多余是必须的而且是非常有用的。在这个模块中,有一些相对来说比较重要的操作函数,下面我和大家一一分享。void establishpagelist( DoubleList *pages )这个函数根据存储的文件,将所有的页建立为链表结构同时初始化相应的页结构信息。但是此时页的内容并没有加载到内存。也就是说,这里是一种延后加载的策略。void storepageinfo( DoubleList *pages, FILE *fp )这个函数根据链表中页的信息将其保存到文件的末尾。void mergefilefrompages( DoubleList *pages, FILE *fp )这个函数将各个页中的内容整合后再保存到文件。保存的格式就是按照上面所列出的那样。void loadpagefromorifile( Page *page )这个函数从原文件加载指定逻辑页的页内容。这个函数之所以是必须的是由于当加载文件的时候建立的页链表信息中的临时文件是空的。客观上说,系统从来没有将页换回磁盘,磁盘上的临时文件是不可能有这个页的内容的。所以此时唯一的策略就是从原文件加载。之所以可以这么做,还是取决于系统存储结构的设计。3.5菜单功能模块为了使得用户操作起来更加方便,系统提供了菜单。在现代图像操作系统的支持下,菜单是一个任何一个应用程序具有的一项非常普遍的功能。但是在早期的操作系统下面,GUI其实是一个奢侈品,所以使用者很多时候必须要和命令行打交道。在该文的设计中,菜单提供了基本的常用功能。其实,很多这中间的功能也有对应的快捷键,不过这么做还是为了更好的人机交互。对于菜单的具体响应,系统都是通过调用前面几个模块中提供的子功能而完成的。当然,这其中也有一些特例。它们也具有自己的一些逻辑处理过程。就总体而言,菜单部分的功能还是包括逻辑上处理和视图上处理两个大的部分。在具体实现中,该文的设计使用了下面的这个二维函数指针数组:int (*menufunctionsCOUNTOFMENUCOUNTOFMENUITEM)(); 初始化模块中将具体的函数调用地址赋值给这个数组。然后,当具体响应功能的时候只要去调用这个地址所指向的具体函数就可以。具体的初始化过程如下:void mapfuncpointers()menufunctions00 = onload;menufunctions01 = onnew;menufunctions02 = onsavefile;menufunctions03 = onsavefileas;menufunctions04 = onexit;menufunctions10 = onfind;menufunctions11 = onreplace;menufunctions12 = oncopy;menufunctions13 = oncut;menufunctions14 = onpaste;menufunctions20 = onchangetextcolor;menufunctions21 = onchangebackcolor;menufunctions22 = ongotoline;menufunctions30 = onabout;其实之所以可以这么做的原因那是由于在C语言中,函数名称的本质就是一个指针,它指向函数执行时候的起始地址。在这样的基础上便可以简单地将函数和菜单功能调用做一个映射。以此同时,系统设置了跟踪菜单选择项的全局变量,当确定之后系统就会利用相应的函数指针来调用正确的菜单处理函数。第4章 系统性能及测试4.1 系统性能及运行结果4.1.1 部分逻辑操作的效率在编辑文本的过程中,使用者一般都会集中在某个区域进行操作。正是由于这样的特点,避免频繁的磁盘读写操作是完全可能的。这里可以称这样的特性叫做编辑的局部性原理。当然,也有一些特殊的操作会打破这个原则,不过那些操作只会以一个小概率发生,所以就整体而言系统的效率不会明显降低。除非特殊操作之外,其他操作最多只会涉及相邻的两个逻辑页。为什么是最多是两个页呢?在谈及逻辑文件页这个概念的时候,文章曾对页的大小有所说明。正是由于页的大小设置和屏幕高度之间的关系决定了在同一时刻,最多只会有两个页出现在平面上。考虑到逻辑页是用一个双向链表串接起来的,所以一般操作下要重新设置当前活动页的效率是O(1)的。因为设计使得实现可以迅速获得此节点的前一个或者是后一个。当确定了当前当前的逻辑文件页之后,具体的行也是实现人员必须要用到的数据。因为在逻辑文件页中存储文本的结构是一个单线性链表,所以具体的查找是一个线性查找,效率是O(n)3。4.1.2 部分刷新操作的效率当逻辑上的操作完成之后,同时界面上也必须反映出这样的变化,系统就有必要刷新屏幕。显然,这个部分的效率是至关重要的。系统实现者不希望在刷新屏幕时,用户会感觉到明显的延时。出于这个考虑,实现人员在各个不同功能的显示响应的时候充分考虑这些因素。最后设计中采取这样的策略:仅仅刷新有限需要刷新的区域,这样的话可以避免没有必要的重复刷新。但是,当待定刷新区域无法确定的时候,系统就会去刷新整个屏幕。当然这样的情况不是很多,但是它确是不想被见到的情况。假设屏幕的宽度是W,高度是H,下面开始分析下重要的刷新的函数的效率情况:void refreshline( int line, int sc, int ec, char *str )这是刷新行函数的定义,从中可以看到此函数将把line行从sc列刷新到ec列。显然这个函数的效率是O(W)。void refreshcolumn( int column )这是刷新列的函数的定义,它会根据逻辑数据刷新column这列的数据。其效率是O(H)。void refreshscreen()这是刷新屏幕的函数定义,它将整个屏幕刷新。又上面的两个函数,显然可以知道这个函数的执行效率是O( W * H )。4.1.3 程序的运行结果图 4-1:运行时效果图4.2 系统的测试4.2.1 测试工程的建立系统的设计使得逻辑和视图可分,所以单独测试逻辑的正确性是可能的。将必要的头文件和逻辑实现整合到一个工程中,然后就可以用预设的测试案例来校验实现是否符合要求。图 4-2:测试工程的结构图4.2.2 单元测试部分单元测试就是要对各个独立的组建进行测试。在这个部分,实现人员单独测试了各个逻辑功能。例如:测试了逻辑上对于方向键、回车键,删除键等的响应。程序结束运行之后将结果与原先的结果进行比对,这里就不将具体的测试用例列出来。4.2.3 集成测试部分集成测试就是为了将由于各组件集成而产生的潜在问题加以暴露。在对各个单个逻辑功能进行测试之后,再在同一个测试案例中加入多个组合功能,也就是从逻辑上去模仿实际中的编辑过程。在这样的情况下,将各个模块进行任意组合进行集成测试。然后再判断结果是否和设想的相符合。当然在测试过程中,实现人员也进行了必要的回归测试。4.2.4 系统测试部分最后在程序完成之后,实现人员对系统进行了一个综合的测试。这个测试是写在DOS平台下的,此时测试人员随意的操作就像真正的用户那样,测试事实上也的确让很多逻辑上处理的瑕疵得到了暴露。值得庆幸的是,问题都被逐一解决了。第5章 总结毕业设计单是实现大概就有2个月之久,如果加上前期的规划和设计那时间就更长了。当再来回顾这段时间的时候,大家觉得非常欣慰,因为整个团队从这次毕业设计的整个过程中是受益匪浅。整个过程中,让大家获益最多的就是相对底层的实现。无论是对基础数据结构的支持,或者是为了节省内存而设计的逻辑文件页这样的概念,还是其他基础操作的内在逻辑性,这些对大家思考问题和解决问题的能力都提出了前所未有的挑战。这次自主选择的课题,从某种程度上说让大家达到了既定目标:体会计算机核心的知识以及底层编程的艺术。同时,大家还加深了对计算机程序执行的原理的理解。比如:指针的更本质的东西,动态内存的分配,以及编译器对待结构体的一些处理方式等。尽管其中一部分推测有待求证,可是大家没有想到自己会做出这些猜想。大家都知道一个人的思维能力对于自身的发展是十分重要的,团队选择的毕业设计使得这个方面的能力得到激发。除此之外,整个毕业设计也让组员加强了团队合作方面的能力。毕竟这个工程量还是挺大的,这也主要是由于没有现成的软件包可以使用,大家必须从头到尾为其功能实现提供一切组件。当然在这个途中也遇到了不少困难,其中一次真的给大家带来了很大的危机。后来在一个学长的指导下,最后团队一起解决了这个问题。大家就是这样在遇到困难和解决困难中不
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 钢丝绳使用及要求
- 校本课程教学计划课程设计
- 2025年国际贸易经理人高级实战模拟考试题库
- 2025年公务员考试行测答题技巧与思路解析
- 湖南省永州市蓝山县第二中学2024-2025学年高二上学期期中考试物理试题(原卷版)
- 电力领域智能电网建设与运营维护方案
- UIUX设计入门实战指南
- 2025年会计从业资格无纸化考试模拟试题及答案
- (2025年标准)股权激励 退出协议书
- 2025年数字孪生技术初级考试必-备知识点与模拟题解析
- 走进奇妙的几何世界
- 飞虎队精神将永远留在这里
- 湘教版九年级美术教学计划(三篇)
- 紧急宫颈环扎术的手术指征及术后管理-课件
- “三重一大”决策 标准化流程图 20131017
- Cpk 计算标准模板
- 信息科技课程标准新课标学习心得分享
- 环保与物业公司合作协议
- FZ/T 01057.2-2007纺织纤维鉴别试验方法 第2部分:燃烧法
- 面条制品-课件
- 四上科学第一单元《多样的动物》知识梳理
评论
0/150
提交评论