【基本要求】
(1)输出文件中字与字之间只留一个空格符,即实现多余空格符的压缩。 (2)在输出文件中,任何完整的字仍不能分割在两行,行尾不齐没关系,但行首要对齐(即左对齐)。
(3)如果所要求的每页页底所空行数不少于3,则将页号印在页底空行中第2行的中间位置上,否则不印。
(4)版面要求的参数要包含:
页长(PageLength)一一每页内文字(不计页号)的行数。 页宽(PageWedth)一一每行内文字所占最大字符数。 左空白(LeftMargin)-一一每行文字前的固定空格数。 头长(HeadingLength)一一每页页顶所空行数。
脚长(FootingLength)一一每页页底所空行数(含页号行)。 起始页号(StartingPageNumber)一一首页的页号。 【测试数据】
略。注意在标点之后加上空格符。 【实现提示】
可以设:左空白数×2+页宽<=160,即行印机最大行宽,从而只要设置这样大的一个行缓冲区就足够了,每加工完一行,就输出一行。
如果输入文件和输出文件不是由程序规定死,而是可由用户指定,则有两种做法:一是像其他参量一样,将文件名交互地读入字符串变量中;更好的方式是让用户通过命令行指定,具体做法依机器的操作系统而定。
应该首先实现GetAWord(w)这一操作,把诸如行尾处理、文件尾处理、多余空格符压缩等一系列\低级\事务留给它处理,使系统的核心部分集中对付排版要求。
每个参数都可以实现缺省值②设置。上述排版参数的缺省值可以分别取56,60,10,5,5和1。 【选作内容】
(1)输入文件名和输出文件名要由用户指定。
(2)允许用户指定是否右对齐,即增加一个参量\右对齐否
11
\缺省值可设为\。右对齐指每行最后一个字的字尾要对齐,多余的空格要均匀分布在本行中各字之间。
(3)实现字符填充(characterstuffing)技术。\作为分段控制符之后,限制了原文中不能有这样的字。现在去掉这一限制:如果原文中有这样的字,改用两个\并列起来 表示一个\字。当然,如果原文中此符号夹在字中,就不必特殊处理了。
(4)允许用户自动按多栏印出一页。
12. 简单行编辑程序
【问题描述】
文本编辑程序是利用计算机进行文字加工的基本软件工具,实现对文本文件的插入、删除等修改操作。限制这些操作以行为单位进行的编辑程序称为行编辑程序。
被编辑的文本文件可能很大,全部读入编辑程序的数据空间(内存)的作法既不经济,也不总能实现。一种解决方法是逐段地编辑。任何时刻只把待编辑文件的一段放在内存,称为活区。试按照这种方法实现一个简单的行编辑程序。设文件每行不超过320个字符,很少超过80个字符。 【基本要求】
实现以下4条基本编辑命令:
(1) 行插入。格式:i<行号><回车><文本>.<回车>
将<文本>插入活区中第<行号>行之后。 (2) 行删除。格式:d<行号l>[<空格><行号2>]<回车>
删除活区中第<行号l>行(到第<行号2>行)。例如:\和\。 (3) 活区切换。格式n<回车>
将活区写入输出文件,并从输入文件中读入下一段,作为新的活区。 (4) 活区显示。格式:p<回车>
逐页地(每页20行)显示活区内容,每显示一页之后请用户决定是否继续显示以后备页(如果存在)。印出的每一行要前置行号和一个空格符,行号固定占4位,增量为1。
12
各条命令中的行号均须在活区中各行行号范围之内,只有插入命令的行号可以等于活区第一行行号减1,表示插入当前屏幕中第一行之前,否则命令参数非法。 【测试数据】
自行设定,注意测试将活区删空等特殊情况。 【实现提示】
(1)设活区的大小用行数ActiveMULen(可设为100)来描述。考虑到文本文件行长通常为正态分布,且峰值在60到70之间,用320×ActiveMULen大小的字符数组实现存储将造成大量浪费。可以以标准行块为单位为各行分配存储,每个标准行块可含81个字符。这些行块可以组成一个数组,也可以利用动态链表连接起来。一行文字可能占多个行块。行尾可用一个特殊的ASCII字符(如(012)8)标识。此外,还应记住活区起始行号。行插入将引起随后各行行号的顺序下推。
(2)初始化函数包括:请用户提供输入文件名(空串表示无输入文件)和输出文件名,两者不能相同。然后尽可能多地从输入文件中读入各行,但不超过ActiveMULen-LX的值可以自定,例如20。
(3)在执行行插入命令的过程中,每接收到一行时都要检查活区大小是否已达ActiveMaxLen。如果是,则为了在插入这一行之后仍保持活区大小不超过ActiveMaxLen应将插入点之前的活区部分中第一行输出到输出文件中;若插入点为第一行之前,则只得将新插入的这一行输出。
(4)若输入文件尚未读完,活区切换命令可将原活区中最后几行留在活区顶部,以保持阅读连续性;否则,它意味着结束编辑或开始编辑另一个文件。
(5)可令前三条命令执行后自动调用活区显示。 【选作内容】
(1)对于命令格式非法等一切错误作严格检查和适当处理。
(2)加入更复杂的编辑操作,如对某行进行串替换;在活区内进行模式匹配等,格式可以为S<行号>@<串1>@<串2><回车>和m<串><回车>。
13
13. 串基本操作的演示
【问题描述】
如果语言没有把串作为一个预先定义好的基本类型对待,又需要用该语言写一个涉及串操作的软件系统时,用户必须自己实现串类型。试实现串类型,并写一个串的基本操作的演示系统。 【基本要求】
在教科书4.2.2节用堆分配存储表示实现HString串类型的最小操作子集的基础上,实现串抽象数据类型的其余基本操作(不使用C语言本身提供的串函数)。参数合法性检查必须严格。
利用上述基本操作函数构造以下系统:它是一个命令解释程序,循环往复地处理用户键入的每一条命令,直至终止程序的命令为止。命令定义如下:
(1)赋值。 格式: A <串标识> <回车>
用<串标识>所表示的串的值建立新串,并显示新串的内部名和串值。例:A ‘Hi!’
(2)判相等。格式: E <串标识1> <串标识2> <回车> 若两串相等,则显示\否则显示\。 (3)联接。 格式:C <串标识1> <串标识2> <回车> 将两串拼接产生结果串,它的内部名和串值都显示出来。 (4)求长度。格式:L〈串标识> <回车> 显示串的长度。
(5)求子串。格式:S <串标识> +<数1>+<数2><回车>
如果参数合法,则显示子串的内部名和串值。<数>不带正负号。 (6)子串定位。格式:I <串标识1> <串标识2> <回车> 显示第二个串在第一个串中首次出现时的起始位置。
(7)串替换。格式: R <串标识1> <串标识2> <串标识3> <回车> 将第一个串中所有出现的第二个串用第三个串替换,显示结果串的内部名和串值,原串不变。
(8)显示。格式:P <回车>
14
显示所有在系统中被保持的串的内部名和串值的对照表。 (9)删除。格式:D <内部名> <回车> 删除该内部名对应的串,即赋值的逆操作。 (10)退出。格式:Q <回车> 结束程序的运行。
在上述命令中,如果一个自变量是串,则应首先建立它。基本操作函数的结果(即函数值)如果是一个串,则应在尚未分配的区域内新辟空间存放。 【测试数据】
自定。但要包括以下几组:
(1)E ‘’ ‘’<回车>,应显示\。
(2)E ‘abc’ ‘abcd’<回车>,应显示\。 (3)C ‘ ‘ ‘ ‘ <回车>,应显示\。
(4)I ‘a’ ‘’ <回车>,应报告:参数非法。 (5)R ‘aaa’ ‘aa’ ‘b’<回车>,应显示'ba’
(6)R ‘aaabc’ ‘a’ ‘aab’<回车>,应显示’aabaabaabbc’。 (7)R ‘Faaaaaaaa’ ‘aaaa’ ‘ab’,<回车>,应显示’abab’。 【实现提示】
【选作内容】
(1) 串头表改用单链表实现。
(2) 对命令的格式(即语法)作严格检查,使系统既能处理正确的命令,也能处理错误的命令。注意,语义检查(如某内部名对应的串已被删除而无定义等)和基本操作参数合法性检查仍应留给基本操作去做。
(3) 支持串名。将串名(可设不超过6个字符)存于串头表中。命令(1)(3)(5)要增加命令参数<结果串名>;命令(7)中的<串标识1> 改为<串名>,并用此名作为结果串名,删除原被替串标识,用<串名>代替<串标识>定义和命令解释中的内部名。每个命令执行完毕时立即自动删除无名串。
15