一、需求分析
系统名称为:行编辑器。它通过利用行编辑器实现了删除某个元素、删除整行元素以及输入数据并保存到文件的功能。
二、概要设计
1、主程序的流程说明
在主程序中,能够实现文本内容的输入、显示、删除和退出编译器等基本功能。该程序实现了对数据的输入、输出,以及对整行数据的删除,对行数据中某个数据的删除,对输入的数据进行写入文件等等。
(1)在行尾回车,整行会被确认并写入文件;
(2)在行尾输入@,可以对整行数据进行删除;
(3)在需要删除的某个元素后输入#可以对该元素进行删除。
2、程序中用到的数据逻辑结构描述及其上定义的函数的描述
程序中运用了栈的静态分配顺序存储结构,它使用了数组来实现栈中元素的存储,并设置了存储栈元素的数组长度为MaxSizwe。
(1)top为整数且指向栈顶元素的下一个位置;
(2)top为整数且指向栈顶元素。
3、存储表示
#define MAXSIZE 100
typedef struct
{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
//1.栈的初始化
int InitStack(SqStack *S)
{
S->base=(SElemType *)malloc( MAXSIZE * sizeof( SElemType ) ) ;
if( !S->base )
{
printf( "分配存储空间失败!\n") ;
return 0;
}
S->top=S->base;
S->stacksize=STACK_INIT_SIZE;
return 1 ;
}
//2.销毁栈
int DestroyStack(SqStack *S)
{
free( S->base ) ;
S->base = NULL ;
S->top = NULL ;
S->stacksize = 0 ;
return 1 ;
}
//3.判断栈是否为空
int StackEmpty(SqStack *S)
{
if(S->top==S->base)
return 1 ;
else
return 0 ;
}
//4.将S重置为空栈
int ClearStack( SqStack *S )
{
S->top = S->base ;
return 1 ;
}
//5.读取栈顶元素
int GetTop( SqStack *S )
{
if( S->base == S->top )
{
printf( "空栈,无法读取!\n" ) ;
return 0 ;
}
return *(S->top - 1 );
}
//6.求栈的长度
int StackLength( SqStack *S )
{
return (S->top-S->base) ;
}
//7.入栈
int Push( SqStack *S , SElemType e )
{
/* 栈满时申请分配新的空间
if( StackLength( S ) == S->stacksize )
{
S->base = ( SElemType* )realloc( S->base , (S->stacksize +
STACK_INCR_SIZE) * sizeof( SElemType ) ) ;
if( !S->base )
{
printf( "分配存储空间失败!\n" ) ;
}
S->top = S->base + S->stacksize ;
S->stacksize += STACK_INCR_SIZE ;
}*/
if( StackLength( S ) == S->stacksize )
{
printf( "栈已满!\n" ) ;
return 0 ;
}
*(S->top)++=e;
return 1 ;
}
//8.出栈
int Pop( SqStack *S , SElemType *e )
{
if(S->top==S->base)
{
printf( "空栈!\n" ) ;
return 0 ;
}
*e=*--S->top;
return 1 ;
}
//9.遍历栈,从栈底到栈顶依次输出栈S中的所有元素
int StackTraverse( SqStack *S )
{
if( S->base == S->top )
{
printf( "空栈!\n" ) ;
return 0 ;
}
SElemType *p = S->base ;
while( p != S->top )
{
printf( "%c\t" , *p++ ) ;
}
printf( "\n" ) ;
return 1 ;
}
//10.将栈写入文件
int StackToFile( SqStack *S )
{
FILE *fp = fopen( "./stacktofile.txt" , "a+" ) ; //"a+" 以读写的形式打开文件
fwrite( S->base , sizeof( SElemType ) , StackLength( S ) , fp )
三、详细设计
行编辑器的功能设计
1)删除某个元素
功能分析
在某个元素后输入@时,可以对某个元素进行删除。
代码实现 case语句
case '#' : //在需要删除的某个元素后面输入#可以对该元素进行删除if( StackEmpty( &S ) )
{
printf( "该行无信息!\n" ) ;
}
Pop( &S , &tmp ) ;
if( tmp == '\\' )
{
Push( &S , ch ) ;
}
break ;
2) 删除整行元素
功能分析
当在行尾输入@时,可以对整行元素进行删除;当在数据后输入\\@时,可以删除一个\,输出为元素加\@。
代码实现 case语句
case '@' : //对整行进行删除
if( StackEmpty( &S) )
{
printf( "该行无信息!\n" ) ;
}
Pop( &S , &tmp ) ;
if( tmp == '\\' )
{
Push( &S , ch ) ;
}
else
{
ClearStack( &S) ;
}
break ;
3)输入数据并保存到文件
功能分析
定义一个主函数StackToFile( SqStack *S ),用fopen()函数打开指定路径的文件,获取指向该文件的指针,再使用fwrite()函数将一块内存区域中的数据写入到本地文本。
代码实现 case语句
//10.将栈写入文件
int StackToFile( SqStack *S )
{
FILE *fp = fopen( "./stacktofile.txt" , "a+" ) ;//"a+" 以读写的形式打开文件
fwrite( S->base , sizeof( SElemType ) , StackLength( S ) , fp ) ; //1.读写数据的地址;2.要读写的字节数;3.要读写多少个数据项;4.文件类型指针
fclose( fp ) ;
return 1 ;
}
四、调试分析
1.问题与对策
(1)问题:结构体成员引用符使用错误。
对策:将引用符". " 改为指针的箭头运算符 ‘’->’’。
2.基本操作的算法复杂度分析
(1)空间复杂度
在入栈和出栈过程中,只需要一两个临时变量存储空间,所以空间复杂度是 O(1)。
(2)时间复杂度
对于出栈操作来说,不涉及内存的重新申请和数据的搬移,所以出栈的时间复杂度仍然是 O(1)。对于入栈操作来说,当栈中有空闲空间时,入栈操作的时间复杂度为 O(1),但当空间不够时,就需要重新申请内存和数据搬移,所以时间复杂度为O(n)。对于入栈操作来说,最好情况时间复杂度是 O(1),最坏情况时间复杂度是 O(n)。
五、测试结果
- 删除某个元素
2.删除整行元素
3.输入数据并保存