参考简单行编辑程序报告.docx
《参考简单行编辑程序报告.docx》由会员分享,可在线阅读,更多相关《参考简单行编辑程序报告.docx(27页珍藏版)》请在冰豆网上搜索。
![参考简单行编辑程序报告.docx](https://file1.bdocx.com/fileroot1/2023-2/24/eb8685e3-61c8-44af-96d0-ce09fa776648/eb8685e3-61c8-44af-96d0-ce09fa7766481.gif)
参考简单行编辑程序报告
沈阳航空工业学院
课程设计
简单的行编辑程序
班级/学号6402103/077_
学生姓名赵壮
指导教师张雷
沈阳航空工业学院
课程设计任务书
课程名称软件技术基础课程设计
院(系)电子信息工程学院专业电子信息工程
班级6402103学号200604021077姓名赵壮
课程设计题目简单行编辑程序
课程设计时间:
2008年7月14日至2008年7月27日
课程设计的内容及要求:
[问题描述]文本编辑程序是利用计算机进行文字加工的基本软件工具,实现对文本文件的插入、删除等修改操作。
限制这些操作以行为单位进行的编辑程序称为行编辑程序。
被编辑的文本文件可能很大,全部读入编辑程序的数据空间(内存)的作法既不经济,也不总能实现。
一种解决方法是逐段地编辑。
任何时刻只把待编辑文件的一段放在内存,称为活区。
试按照这种方法实现一个简单的行编辑程序。
设文件每行下超过320字符,很少超过80字符。
[基本要求]实现以下4条基本编辑命令:
(1)行插入。
格式:
i<行号><回车><文本>.<回车>将<文本>插入活区中第<行号>行之后。
(2)行删除。
格式:
d<行号l>[<空格><行号2>=<回车>删除活区中第<行号1>行(到第<行号2>行=。
例如:
“d10┛”和d1014┛”
(3)活区切换。
格式:
n<回车>将活区写入输出文件,并从输入文件中读入下一段,作为新的活区。
(4)活区显示。
格式:
p<回车>逐页地(每页20行)显示活区内容,每显示一页之后请用户决定是否继续显示以后各页(如果存在)。
印出的每一行要前置以行号和一个空格符,行号固定占4位.增量为l。
各条命令中的行号均须在活区中各行行号范围之内,只有插入命令的行号可以等于活区第一行行号减l,表示插入当前屏幕中第一行之前,否则命令参数非法。
指导教师年月日
负责教师年月日
学生签字年月日
简单的行编辑
一、题目分析
通过对该软件课设的分析,了解到该课设要求设计一个程序,能够实现行插入、行删除、活区显示、活区切换四项功能。
分别设计出四个模块,用主函数集中调度,这样就可以方便快捷的实现各个函数以及整体函数的功能。
其具体做法是,先在程序的开始定义一个结构体,其中包括五个数据项,分别是存储每一行元素的项charstring[80]、指向前一个结点的指针structtext*pre、指向后一个结点的指针structtext*next、记录每一行元素的长度intnum以及判断是否删除的标志intflat。
当flat=0时,该行被删除;当flat=1时,该行不删除。
对文本的编辑,每次都采用先打开文本文件的形式,因为这样可以更直观的看出编辑后文本的变化。
实现活区显示的做法是建立一个链表,该链表有20个结点,在一页中放不下的部分为活区,执行p后可以显示出第一页的部分,在continue之后选择Y便可以显示出活区的部分,即第二页的内容。
实现活区切换的做法是执行n后,先判断活区的内容,如果没被删除就把文本中内容读入到链表中,便可以直接显示出获取部分,即第二页的内容。
实现删除的做法是执行d,定义两个指针分别指向要删除的结点,删除两个结点之间的内容,最后将删除后的结果存盘并显示下一页内容。
实现插入的做法是执行i,定义一个指针变量插入行的前一行,然后给插入行分配存储空间,将插入行的内容插入到链表中,便实现行插入的功能。
程序还定义了一个函数来释放所占链表的内存,在退出程序后利用保存函数将内容存盘.
二、设计过程(程序流程图)
1.主函数的设计
主函数采用do—while循环,循环体主要调用三个子函数:
1EDIT(),2HELP(),3EXIT()。
行编辑程序的四种主要功能都在EDIT()编辑函数中执行。
HELP()函数是提示用户各种功能的执行方式,主函数通过给字符变量cmd赋初值来选择是结束程序还是继续执行循环体中的内容。
主程序流程图如1所示。
图1主函数流程图
2.帮助函数HELP()子程序设计
帮助函数的主要作用是在用户忘记如何操作的情况下在屏幕上给用户显示提示操作的信息,使行插入,行删除,活区显示,活区切换的执行方式,其流程图如图2所示。
图2帮助函数HELP()流程图
3.编辑函数EDIT()子程序设计
简单行编辑程序的各种功能在编辑函数中实现。
首先给字符型变量cmd赋初值,通过switch(cmd)来选择执行哪种功能。
退出编辑函数:
E(e),调用saveall()函数将内容存盘,然后调用freemem()释放链表空间。
打开文件:
O(o),调用openfiles()函数打开文件。
执行活区显示:
P(p)。
执行行删除:
D(d)。
执行行插入:
I(i)。
执行活区切换显示:
N(n)。
程序流程图如图3所示。
图3编辑函数流程图
4.活区显示函数display()子程序设计
在活区显示中首先把文本内容链入链表,函数中用page来实现页码的自增。
函数种定义了一个指向structtext结构体的指针变量p,在文件fp非空和行号小于20的情况下,利用fgets函数使p->string从打开的文件fp中得到字符的值,然后输出每一行的行号和每一行的内容,在此函数的最后还可以利用Y和N来决定是否继续显示下一个活区的内容。
其程序流程图如图4所示。
图4活区显示函数流程图
5.活区切换函数saveanddisplay(20)子函数设计
活区切换函数实现活区之间的切换,把文本的每一页(20行)作为一个活区,可以逐页的把活区内容显示出来。
在活区切换函数中定义了一个指向structtext结构体的指针变量p赋初值*p=NULL,当i小于20时,如果行没有被删除(flag=1)就通过fputs函数把活区内容写入到文件(out).打开文件fp,如果文件非空,用fgets函数从文件fp读入字符串,并用puts函数输出。
如果文件fp为空就输出fileend!
。
程序流程图如图5所示。
图5活区切换函数流程图
6.行删除函数del()子程序设计
在函数的开始定义了三个指向structtext结构体的指针变量p1,p2,p3。
输入要删除的两个行号(比如13),表示删除从第1行到第3行的数据。
程序流程图如图6所示。
图6行删除函数流程图
7.行插入行数insert()子程序的设计
行插入函数的开始定义了三个指向structtext结构体的指针变量p,p1,p2,在给hang赋初值后使p1指向头结点,利用for循环,找到要插入行的前一行hang-1,然后给插入的行分配内存空间。
输入文本内容并连入链表。
行程序流程图如7所示。
图7行插入函数流程图
三、调试过程及实验结果
(1)调试过程
在程序编写好之后,便开始在VC中编译执行程序,虽然程序没有错误,但是执行过程中插入可以实现,删除却实现不了,在仔细检验程序后,发现在执行过程中没有先打开文件,因此无法继续执行。
再改正之后便可以得到正确的运行结果了。
(2)实验结果
1.帮助函数HELP()调试结果
在执行过程中按2键便可进入到帮助菜单中,其中有四种功能,其结果如下图。
图8HELP()函数的内容
2.打开文件函数openfiles()调试结果
在命令窗口输入1调用EDIT()函数,输入O,回车后,输入你想打开的文本名,回车后,输入你想写入的文本名。
结果如图9所示。
图9打开文件命令调试结果
3.活区显示函数display()调试结果
打开文件后输入P,回车后显示每一页的内容(即活区内容),输入Y是继续显示下一页的内容,调试结果如下面图所示。
图10第一页活区的内容
图11第2页活区的内容
4.活区切换函数saveanddisplay()调试结果
例如在活区显示完第1页后,输入N,程序等待你输入下一个命令,这时输入n,回车后显示下一活区内容,也就是第二页的内容。
调试结果如下图所示。
图12输入命令n
图13第2页活区的内容
5.行删除函数del()调试结果
先进入EDIT,打开文件,观察原始数据。
输入d后,根据提示信息输入最小行号和最大行号(例如13),回车后显示删除后的内容。
如下图所示。
图14观察原始数据结果
图15行删除函数调试结果
6.行插入函数insert()调试结果
接着在行删除函数执行后输入命令i,回车,然后输入你想插入的行号(例如3),回车后输入你想插入的文本内容(如00000000000000000000^,“^”是文本结束的标志),回车后会显示修改后的链表,即插入行后的文本内容,如图16所示。
图26行插入调试结果
四、结论
通过对该题目的编写调试以及结果显示可以看出,本程序可以满足任务书的要求,实现了对行的插入、删除、活区显示、活区转换的各项要求。
在执行插入命令的过程中,要检验活区的大小,如果插入这一行之后,仍保持不超的话,就将其插入。
在输入未读完时,可将未读完的内容保持在活区的顶部。
此外,也实现了一些简单的操作,例如,创建了一个链表,实现文本文件的打开,实现以行为单位是很合理的。
通过这次课设,了解简单行编辑程序应用的广泛性。
本课程设计的简单行编辑程序各功能的运行操作十分快捷,能满足用户的需要。
5、程序清单
#defineNULL0
#defineOK0
#include
#include
#include
#include
#include
typedefstructtext
{
charstring[80];//存储每一行的元素
structtext*next;//指向后一个节点的指针
structtext*pre;//指向前一个节点的指针
intnum;//每一行元素的长度
intflat;//确定此行是否被删除的标志
}text;
FILE*fp,*out;//fp是执行被打开的文件,out指向被写入的文件
text*head;//链表的头指针
intn=0,sum,delnum,xiugai=0,page=0;
//修改用来指示文件是否被修改过,如果修改过才回存盘。
page用来计算显示的
//页数.delnum用来存储被删除的字节数,sum存储一页的总字节数
voidHELP()//帮助函数,显示一些命令的格式
{
printf("\n\t**********************************************************\n");
printf("\t**打开文件:
o<行号><文件名><回车>**\n");
printf("\t**行插入格式:
i<行号><回车><文本><回车>**\n");
printf("\t**行删除格式:
d<行号1>[<空格><行号2>]<回车>**\n");
printf("\t**活区切换格式:
n<回车>**\n");
printf("\t**活区显示格式:
p<回车>**\n");
printf("\t**注意:
在执行所有命令前必须先用o命令打开文件,并**\n");
printf("\t**用p命令显示出来!
!
!
**\n");
printf("\t**********************************************************\n");
printf("\n\n\n");
system("pause");
}
voidCreatelist()//建立一个二十个节点的链表,是文本中的一页
{
text*p1,*p2;
p1=p2=(text*)malloc(sizeof(text));//分配空间
head=NULL;
while(n<20)
{
n=n+1;
if(n==1)head=p1;
else
{
p2->next=p1;//p2->pre=p1;p1->next=p2;p1=p2;
p1->pre=p2;
p1->flat=0;
}
p2=p1;
p1=(text*)malloc(sizeof(text));
}
p2->next=NULL;
}
voidfreemem()//释放链表所占的内存
{
text*p;
for(p=head;head!
=NULL;)
{
head=p->next;
free(p);
p=head;
}
}
intEDIT()//编辑函数,用来接受处理编辑命令
{
charcmd;
do
{
cmd=getchar();
printf("\n请输入命令(按E键退出):
\n");
cmd=getchar();
switch(cmd)
{
case'e':
case'E':
if(xiugai==1)
saveall();
freemem();
if(fp)
fclose(fp);
if(out)
fclose(out);
system("cls");
return0;
case'o':
//打开文件
case'O':
Openfiles();
break;
case'p':
//活区显示
case'P':
Createlist();
display();
break;
case'n':
//活区转换
case'N':
saveanddisplay(10);
break;
case'd':
//删除行
case'D':
del();
break;
case'i':
//插入行
case'I':
insert();
break;
default:
printf("\n\n\n!
!
!
输入错误!
!
!
");
}
}
while(cmd!
='e'&&cmd!
='E');
return0;
}
intOpenfiles()//打开文件的函数
{
charname[30],outname[30];
puts("请输入要打开的文件名:
");
scanf("%s",name);
if((fp=fopen(name,"r+"))==NULL)
{
printf("打不开原文件!
\n");
exit(0);
}
puts("请输入要写入的文件名:
");
scanf("%s",outname);
if((out=fopen(outname,"w+"))==NULL)
{
printf("打不开目标文件!
\n");
exit(0);
}
return0;
}
intdisplay()//从文件中读入到链表中,并显示出来
{
inti;
charconti='y';
text*p;
while((!
feof(fp))&&(conti=='y'||conti=='Y'))
{
page++;
printf("\n第%d页\n",page);
for(i=0,p=head,sum=0;(i<10)&&(!
feof(fp));i++,p=p->next)
{
fgets(p->string,sizeof(p->string),fp);
puts(p->string);
p->flat=1;
p->num=strlen(p->string);
sum=sum+p->num;
}
puts("Continue?
(Y/N):
");
conti=getche();
if(feof(fp))
{
puts("\n文件已经结束!
");
return0;
}
}
return0;
}
intsaveanddisplay(inthang)//命令n执行的函数,用来将活区的内容显示并读入下一页内容
{
inti,endflat=0;
charconti='y';
text*p=NULL;
page++;
for(i=0,p=head;inext)//将活区写入文件
if(p->flat==1)
{
fputs(p->string,out);
p->flat=0;
}
if(!
feof(fp))
printf("\t\t第%d页\n",page);
for(i=0,p=head,sum=0;(i<10)&&(!
feof(fp));i++,p=p->next)//从文件读入活区
if(fgets(p->string,sizeof(p->string),fp))
{
puts(p->string);
p->flat=1;
p->num=strlen(p->string);
sum=sum+p->num;
}
if(feof(fp))
printf("文件已经结束!
");
return0;
}
intsaveall()//退出编辑函数后执行的函数,将所有的内容存盘
{
inti,endflat=0;
charconti='y';
text*p;
for(i=0,p=head;i<10;i++,p=p->next)//将活区写入文件
if(p->flat==1)
{
fputs(p->string,out);
p->flat=0;
}
while(!
feof(fp))//将其余的内容写入文件
fputc(fgetc(fp),out);
return0;
}
intdel()//删除d命令对应的函数,用来删min-max中的行,用结构体中的flat表示是否被删除
{
text*p1,*p2,*p3;
intmin,max,i;
xiugai=1;
scanf("%d%d",&min,&max);
if(head==NULL)
{
printf("\nlistnull!
\n");
return0;
}
p1=p2=head;
for(i=0;ip1=p1->next;
for(i=0;ip2=p2->next;
for(delnum=0;p1!
=p2;p1=p1->next)/*删除中间的节点,将flat赋值0*/
{
p1->flat=0;
delnum=delnum+p1->num;
}
for(i=0,p3=head;i<10;i++,p3=p3->next)//显示删除后的结果
if(p3->flat==1)
puts(p3->string);
saveanddisplay(10);//将删除后的结果存盘并显示下一页内容(十行)
xiugai=1;
return0;
}
intinsert()//插入i命令对应的函数,在i行后插入文本
{
inthang,i,increhang=1,number=1;
text*p,*p1,*p2;
xiugai=1;
printf("输入要插入的行号\n");
scanf("%d",&hang);
p=NULL;
p1=NULL;
for(i=0,p1=head;inext);//找到要插入行的前一列
p=(text*)malloc(sizeof(text));//为插入行分配空间
p->flat=1;
p->next=p1->next;//从此行向下四行将插入行插入到链表中
p->pre=p1;
p1->next->pre=p;
p1->next=p;
p->string[0]=getchar();
for(i=1;(i<80)&&(p->string[i-1]!
='^');i++)
{
p->string[i]=getchar();
if((i+1==80)&&(p->string[i]!
='^'))//如果插入的内容超过一行的容量,则分配下一行空间并将其连入链表
{
p1=p;
p=(text*)malloc(sizeof(text));
p->flat=1;
p->next=p1->next;
p->pre=p1;
p1->next->pre=p;
p1->next=p;
i=0;
increhang++;
}
p->num=i;
}
p->string[i-1]='\n';
p->string[i]='\0';
puts("修改后的链表:
");
for(p2=head;p2!
=NULL;p2=p2->next)//显示出修改后的链表
puts(p2->string);
saveanddisplay(10+increhang);//将修改后的链表存盘并显示下一页内容
xiugai=1;
return0;
}
intmain()//主函数,用来接受命令
{
charcmd;
do
{
printf("\n\t\t****************************\n");
printf("\t\t**1EDIT**\n");
printf("\t\t**2HELP**\n");
printf("\t\t**3TEXI**\n");
printf("\t\t****************************\n");
printf("\n\n请选择1:
EDIT,2:
HELP,3:
EXIT:
\n");
cmd=getche();
switch(cmd)
{
case'2':
HELP();
cmd=0;
break;
case'1':
EDIT();
cmd=0;
break;
default:
printf("\n\n\n!
!
!
输入错误!
!
!
\n");
}
}
while(cmd!
='3');
return0;
}