一、需求分析由于被编辑的文本文件可能很大,全部读入编辑程序的数据空间(内存)的作法既不经济,也不总能实现。
而用行编辑把待编辑文件的一段放进内存,称为活区。
本行编辑程序是以每行不超过320个字符为前提的。
每次编辑会读入80行,活区每次只显示20行。
1.该程序要实现以下基本编辑命令和一些相关的命令:(1)行插入。
格式:i<回车><行号><回车><文本><回车>。
将<文本>插入活区第<行号>行之后。
(2)行删除。
格式:d<回车><行号1>,<行号2><回车>。
删除活区中第<行号1>行到第<行号2>行。
(3)活区切换。
格式:n<回车><页数><回车>。
由于每次从输入文件读入80行,而活区每页显示20行,而活区切换就是要切换到需编辑的页面上去。
(4)活区显示。
格式p<回车>。
显示当前要编辑的活区内容。
印出的每一行都有一个前置行号和一个空格符,行号固定为2位,增量为1。
(5)清屏。
格式:c<回车>。
(6)获得帮助。
格式:h<回车>。
(7)退出。
格式:e<回车>。
二、概要设计程序结构流程图:存储结构的定义如下:typedef struct text{char string[80];//存储每一行的元素struct text *next;//指向后一个节点的指针int flat;//确定此行是否被删除的标志}text,*textp;功能函数:Status Createlist(textp &head);功能:建立一个80个节点的链表,是整个活区的大小int del(textp head);功能:删除显示的活区的任意一行。
int display(textp &head);功能:按照每页20行的规格显示活区的内容。
void freemem(textp &head);功能:销毁链表,释放内存。
int insert(textp &head);功能:在显示的活区插入一行内容。
Status SaveFile(textp head,FILE *out);功能:将活区的内容保存到输出文件。
Status LoadFile(textp head,FILE *fp);功能:从输入文件读取内容到活区。
void HELP();功能:提供命令的格式。
主函数:void main(){初始化;输入命令;Switch(c){case ‘e’:退出并保存编辑的内容case ‘p’: 显示活区case ‘n’: 活区切换case ‘d’: 删除一行case ‘i’: 插入一行case ‘c’: 清屏case ‘h’: 获得帮助}}三、详细设计#include<string.h>#include<stdio.h>#include<stdlib.h>#include<io.h>#include<process.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2typedef int Status;typedef struct text{char string[80];//存储每一行的元素struct text *next;//指向后一个节点的指针int flat;//确定此行是否被删除的标志}text,*textp;//函数声明Status Createlist(textp &head);int del(textp head);int display(textp &head);void freemem(textp &head);int insert(textp &head);Status SaveFile(textp head,FILE *out);Status LoadFile(textp head,FILE *fp);void HELP();void main()//主函数,用来接受命令//编辑函数,用来接受处理编辑命令{textp head,q,p,p1;int page=0;FILE *fp,*out;char c,inname[30],outname[30];printf("################################欢迎使用行编辑程序#############################\n");HELP();printf("按任意键开始。
");c=getchar();/*打开输入、输出文件*/printf("Enter the infile name:");scanf("%s",inname);printf("Enter the outfile name:");scanf("%s",outname);if((fp=fopen(inname,"r"))==NULL){ printf("can't open the file! \n");exit(0);}if((out=fopen(outname,"w"))==NULL){ printf("can't open the file!\n");exit(0);}Createlist(head); /*创建一个80个结点的链表*/p=head;LoadFile( head,fp);do{printf("input order:");fflush(stdin);c=getchar();switch(c){case 'e':SaveFile(head,out); /* 退出并保存编辑的内容*/fclose(fp);fclose(out);break;case 'p': q=p;display(p);page++;if(page>4)page=1;printf("**********************page%d************************\n",page);if(page==4){p=head;page=0;}break;case 'n': /*活区切换*/SaveFile(head,out);LoadFile(head,fp);page=1;q=p=head;display(p);printf("**********************page%d************************\n",page);break;case 'd':p=q; /*显示活区*/del(p);display(p);printf("**********************page%d************************\n",page);break;case 'i': /*插入行*/p=q;insert(p);if(head->flat==1)fputs(head->string,out);p=q=q->next;p1=head;head=head->next;free(p1);display(p);printf("**********************page%d************************\n",page);break;case 'c':system("cls");break;case 'h':HELP();break;default:printf("\n\n\ninput error"); /*命令格式非法提示*/}}while(c!='e');freemem(head);}Status Createlist(textp &head)//建立一个80个节点的链表,是整个活区的大小{int n=0;textp p1,p2;p1=p2=(textp)malloc(sizeof(text));head=NULL;while(n<80){n=n+1;if(n==1){ head=p1;head->flat=0;}else{p2->next=p1;p1->flat=0;}p2=p1;p1=(text *)malloc(sizeof(text));}p2->next=NULL;return OK;}int del(textp head)//删除d命令对应的函数,用来删max-min中的行,用结构体中的flat表示是否被删除{text *p1,*p2;int min,max,i;scanf("%d %d",&min,&max);if(head==NULL){printf("\nlist null!\n");return OK;}p1=p2=head;for(i=0;i<min-1;i++)/*找到要删除的第一行*/p1=p1->next;for(i=0;i<max;i++)/*找到要删除的最后一行*/p2=p2->next;for(;p1!=p2;p1=p1->next)/*删除中间的节点,将flat赋值0*/{p1->flat=0;}return OK;}int display(textp &head)//显示P命令对应的函数,用来显示活区的内容{int i;textp p;for(i=1,p=head;i<=20&&p;p=p->next)if(p->flat==1){printf("%2d",i); /*输出每一行的行号*/i++;printf(" %s",p->string);}head=p;return 0;}void freemem(textp &head)//释放链表所占的内存{text *p;for(p=head;head!=NULL;){head=p->next;free(p);p=head;}}int insert(textp &head)//插入i命令对应的函数{int hang,i;textp p,p1;scanf("%d",&hang);p=(textp)malloc(sizeof(text));//为插入行分配空间p->flat=1;fflush(stdin);fgets(p->string,80,stdin); /*输入插入行的内容*/p1=head;if(hang==1){ if(!head->flat) /*头结点已被删除*/for(;p1&&!p1->flat;p1=p1->next); /*找到第一个flat=1的点*/p->next=p1->next;p1->next=p;}else{for(i=1,p1=head;i<hang;p1=p1->next)//找到要插入行的后一行if(p1->flat==1)i++;p->next=p1->next;//从此行向下将插入行插入到链表中p1->next=p;}return OK;}Status LoadFile(textp head,FILE *fp) /*从文件读内容到活区*/{textp p;for(p=head;p&&(!feof(fp));p=p->next){ if(!fgets(p->string,80,fp))break;p->flat=1;}return 0;}Status SaveFile(textp head,FILE *out) /*存储活区的函数*/{ textp p;for(p=head;p;p=p->next)if(p->flat==1){fputs(p->string,out); /*输出活区的内容到指定的文件*/p->flat=0;}return OK;}void HELP()//帮助函数,显示一些命令的格式{printf("\n\t **********************************************************\n"); printf("\t ** 行插入格式:i<行号><回车><文本><回车> **\n");printf("\t ** 行删除格式:d<回车><行号1>[<空格><行号2>]<回车> **\n"); printf("\t ** 活区切换格式:n<回车> **\n");printf("\t ** 活区显示格式:p<回车> **\n");printf("\t ** 清屏格式:c<回车> **\n");printf("\t ** 帮助格式:h<回车> **\n");printf("\t **********************************************************\n");}四、调试分析测试数据:任意的TXT文件,只要每行不超过80个字符。