数据结构课程设计之简易文本编译器(C语言实现)
需求分析
(1)具有图形菜单界面:显示实时年份,日期,星期及时间
(2)
查找:查找文本中的字符串,显示其出现的行数,列数及总共出现次数
替换(等长,不等长):对文本中的文本实现等长及不等长替换
插入(插串,文本块的插入):插入一行或在具体行号列号处插入文本
块移动(行块,列块移动):向下移动一行,向上移动一行,
具体行号列号处向左移动或向右移动
删除:删除一行,删除莫一行,莫列,定长的内容
(3)可正确存盘、取盘;:可读取,保存文本;
(4)正确显示总行数。(行数不少于5行,每行字符数不少于80个字符)
采用的数据结构
1:采用的逻辑结构
文本编辑器主要是针对文本进行编辑,文本的操作就是对字符的操作。文本编辑器可以从行、
列两个方向进行编辑。
每一行可以看成一个线性表,线性表是一种线性结构,线性结构的特点是数据元素之间为线性
关系,据元素“一个接一个的排列”。在一个线性表中数据元素的类型是相同的,由于每一行
可以存储的最大字数是相同的,行方向所有线性表的最大长度可以设置成相同的。行与行之间
的关系也可以看成一个线性表。
2.采用的存储结构
线性表的存储分为两种:顺序存储和链式存储。
顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各元素,用这种存储形式
存储的线性表称为顺序表。在程序设计语言中,一维数组在内存中占用的存储空间就是一组连续
的存储区域,因此,用一维数组来表示顺序表的数据存储区域是再合适不过的。
链式存储是通过-组任意的存储单元来存储线性表中的数据元素的,为建立数据元系之间的线性
关系对每个数据元素除了存放数据元素自身的信息之外,还需要和一起存放其后继或前驱所在的
存储单元的地址,这两部分信息组成一个“结点”,每个元素都如此。存放数据元素信息的称为
数据域,存放其前驱或后继地址的称为指针域。只有一个存储单元地址的为单链表,有两个存储
单元地址的为双链表。
考虑到实际的功能需求,每行的线性表可以用顺序存储方式,每个字符是一个节点。用数组的长
度表示本行可以输入的最大字符。行与行之间的线性表采用双链表存储,每个节点包括四个区域,
一个指针域prior指向上一行,一个指针域next指向下一行,一个数据域num是行号,一个数据
域是本行的字符数组。程序以行和列标识文本位置,行采用双向链表存储行信息,用数组下标标识
列信息,从而能够准确定位字符位置,然后进行查找、替换、插入、块移动、删除等多种操作。
函数功能模块图:
定义的结构体:
struct line
{
char text[MAX_LEN]; //本行的文本
int num; //行号
struct line *next; //指向下一行的指针
struct line *prior; //指向前一行的指针
};
代码如下(仅供参考)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define MAX 240
#define NOT_FOUND -1
//函数声明
void HeadWord(void); //输出大标题,永远出现在程序的最顶端。
void PrintWord(void); //输出文本的内容
void printf_time(); //输出时间和日期,星期及年月日
void scanf_load(); //从键盘录入文本
void file_load(); //把文本文件的内容读到线性表中
void findstr(); //查找字符串
void delete1(int linenum);//删除一行
void delete2(int linenum,int position,int lenth);//删除莫一行,莫列,定长的内容
void insert1(); // 插入一行文字
void insert2(char str[], int linenum, int position);//插入文字到文本莫一行莫一列
void replace(); //替换
void Mainmenu(); //主菜单
void menu1(); //文件录入方式菜单
void menu2(); //文本内容处理菜单
void menu_move(); //移动菜单
//定义结构体
struct line
{
char text[MAX]; //该行的内容
int num; //用来记录行号
struct line *prior; //用来指向前一行
struct line *next; //用来指向下一行
};
struct line *start; //指向线性表的第一行
struct line *last; //指向线性表的最后一行
//主函数
int main()
{
Mainmenu();
return 0;
}
//输出标题,永远出现在程序的最顶端。
void HeadWord()
{
printf("\t\t ____________________________________________________\n\n");
printf("\t\t**** Welcom to use our TXT edition system! ****\n");
printf("\t\t ____________________________________________________\n");
}
// 输出链表的内容
void PrintWord()
{
struct line *p = start;
while(p != last)
{
printf("\n\t\t第%d行|%s",p->num,p->text);
p = p->next;
}
printf("\n\t\t第%d行|%s",last->num,last->text);
printf("\n");
}
//输出时间和日期
void printf_time()
{
time_t timep;
struct tm *p;
time (&timep);
p=gmtime(&timep);
//年月日
printf("\t\t|Data:%d-%d-%d |",1900+p->tm_year,1+p->tm_mon,p->tm_mday);
//显示星期几
printf("Today is ");
switch (p->tm_wday)
{
case 7:
printf("Sunday |");
break;
case 1:
printf("Monday |");
break;
case 2:
printf("Tuesday |");
break;
case 3:
printf("Wednesday|");
break;
case 4:
printf("Thursday |");
break;
case 5:
printf(" Friday |");
break;
case 6:
printf("Saturday |");
break;
default:
break; }
//让时间固定显示为 08:04:11类型,即当时,分,秒小于十时前加零
if(p->tm_hour+8<10&&p->tm_min>10&&p->tm_sec>10)
printf("Time:0%d:%d:%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8<10&&p->tm_min<10&&p->tm_sec>10)
printf("Time:0%d:0%d:%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8<10&&p->tm_min<10&&p->tm_sec<10)
printf("Time:0%d:0%d:0%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8>=10&&p->tm_min<10&&p->tm_sec<10)
printf("Time:%d:0%d:0%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8>=10&&p->tm_min>=10&&p->tm_sec<10)
printf("Time:%d:%d:0%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8>=10&&p->tm_min>=10&&p->tm_sec>=10)
printf("Time:%d:%d:%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8>=10&&p->tm_min<10&&p->tm_sec>=10)
printf("Time:%d:0%d:%d |",p->tm_hour+8,p->tm_min,p->tm_sec);
else if(p->tm_hour+8<10&&p->tm_min>=10&&p->tm_sec<10)
printf("Time:0%d:%d:0%d |",p->tm_hour+8,p->tm_min,p->tm_sec);