成都信息工程学院计算机系
课程实验报告
实验课程: 数据结构
实验项目: 文本编辑器的实现 指导教师: 李莉丽 学生姓名: 陈德怀 学生学号: 2009053035 班 级: 数媒一班 实验地点: 实验时间: 20 10 年 月 日 点~ 点 实验成绩: 评阅老师:
一【上机实验目的】
要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
二【实验环境】
PC机每人1台
三【上机实验内容】
要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
四【上机调试程序流程图】(注:可打印)
在此程序中,主要包含了添加、插入、删除、复制、剪切、粘贴、还有文件操作。
五【上机调试中出现的错误信息、错误原因及解决办法】
1、 开始的时候当我输入字符的时候,总是输不进去,经过检查才知道,我忘了把字符输出
到屏幕上。 2、 在删除的时候,当一行删除完的时候,光标并不会上移到上一行。然后我通过判断当这
光标处的坐标减一后为零(表示这行没有字符了)的时候,然后重新读取光标,让光标显示在上一行。
3、 在进行插入操作之后,移动光标会出现问题,就好像插入的字符并没有在链表当中一样。
然后我写了一个测试函数,来判断插入后链表是否满足每列的字符数不得超过80个字符。然后让每列的字符数都在链表当中,满足要求。
六【上机调试后的源程序及还存在的问题】(注:源程序可打印)
/*文本编辑器editor源代码*/ #include
#include
#include
#define LEFT 0x4b00 /*←:光标左移*/ #define RIGHT 0x4d00 /*→:光标右移*/ #define DOWN 0x5000 /*↓键:光标下移*/
#define UP 0x4800 /*↑键:光标上移*/
#define ESC 0x011b /*ESC键:取消菜单打开操作*/
#define ENTER 0x1c0d /*回车键:换行*/
#define BACK 3592 /*BackSpace键:删除当前光标位置前一个字符*/ #define CL 29440 /*ctrl+←键:从右至左,选定文本*/ #define CR 29696 /*ctrl+→键:从左到右,选定文本*/
#define Cc 11779 /*ctrl+c键:将选定文本,复制一份到剪贴板中*/ #define Cv 12054 /*ctrl+v键:将剪贴板中的内容复制到当前位置*/ #define Cx 11544 /*ctrl+x键:对选定文本,执行剪切操作*/ #define F1 15104 /*F1键:打开文件菜单*/ #define F2 15360 /*F2键:打开编辑菜单*/ #define F3 15616 /*F3键:打开帮助菜单*/
int value,backup;
/*value保存有值数组元素的最大下标值,backup保存value的副本,NUM保存当前行中的用户输入的字符个数*/
typedef struct record {
char ch; /*保存一字符*/
int col, line; /*x轴和y轴坐标*/
}record;
record r[500]; /*定义一个有500个元素的结构体数组,保存选定的文本字符的属性*/
typedef struct node /*定义保存行中的单个字符的结构*/ {
char ch; /*数据域:保存一字符*/
struct node *next; /*指针域:指向下一个结点的指针*/ }node;/*由此类型节点构成的单链表,命名为:列单链表*/
typedef struct Hnode /*定义保存所有列单链表首节点的指针的结构*/ {
node *next; /*指向列单链表的首节点的地址*/ struct Hnode *nextl; /*指向下一个节点的指针*/
}Hnode;/*由此类型节点构成的单链表,命名为:行单链表*/
void view(Hnode *q) /*按行显示保存在单链表中的文本字符,q为指向行单链表中第一个节点的指针*/
{
node *p; /*p为保存列单链表节点元素地址的指针*/
clrscr(); /*清屏*/
/*双重循环,读取并显示保存在单链表中字符*/
do{
p=q->next;
while(p!=NULL&&p->ch>=32&&p->ch<127&&p->ch!=13&&p->ch!=-1) /*指针p不能为空,且数据域必须为常规字符*/
{
putch(p->ch);/*在文本窗口中输出该字符*/ p=p->next; /*指向下一个节点*/ }
q=q->nextl; /*指向下一个节点*/
if((p->ch==13||p->ch==-1)&&q!=NULL) gotoxy(1,wherey()+1); /*若ch为回车或EOF标记,光标跳至下行的开始处*/
}while(q!=NULL); /*逐行逐列显示文本字符*/ }
void control(int A, Hnode *Hhead) {
void colorview(Hnode *,int,int); /*函数声明*/
int x,y,flag=0;
x=wherex(); y=wherey(); /*得到当前光标的坐标值*/
if((A==CL)&&(x!=1)) /*ctrl+←,当前光标不是在行首,光标移动*/ gotoxy(wherex()-1,wherey());
if((A==CL)&&(x==1)) /*ctrl+←,在行首*/
gotoxy(abs(judge(Hhead,wherey()-1)),wherey()-1); /*judge(Hhead,wherey()-1)上一行的字符个数作为x值,光标移动*/
if((A==CR)&&check(Hhead,wherey(),wherex())>0) /*ctrl+→,当前光标的右边有字符,光标移动*/
{ flag=1; gotoxy(wherex()+1,wherey()); }
if((A==CR)&&check(Hhead,wherey()+1,1)>0&&check(Hhead,y,x)==0) /*ctrl+→,当前光标处没有字符但下一行的第一列有字符,光标移动*/ { flag=1; gotoxy(1,wherey()+1); }
if((A==CR)&&x==80) /*ctrl+→,当前光标在当前行的行尾,光标移动*/ { flag=1; gotoxy(1,wherey()+1); }
if(A==CR&&flag==1) /*ctrl+→,光标已经跳至新处,将当前光标所在位置的字符的坐标和值保存在r数组中*/ {
r[abs(value)].col=wherex();
r[abs(value)].line=wherey();
r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col);
if(r[abs(value)].ch==-1) r[abs(value)].ch=13; /*若第line行,第col列的字符为回车键,则返回-1*/ value--;
}
if(A==CL&&(x!=1||y!=1)) /*ctrl+←,当前光标并不在窗口左上角,将当前光标所在位置的字符的坐标和值保存在r数组中*/ {
r[abs(value)].col=wherex(); r[abs(value)].line=wherey();
r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col); value++;
}
colorview(Hhead,wherex(),wherey()); }
/*用不同的前背景色显示选择的字符*/ void colorview(Hnode *Hhead,int x,int y) {
int i;
view(Hhead);/*重新显示所有文本字符*/
for(i=0;i
gotoxy(r[i].col,r[i].line); textcolor(0); textbackground(7); cprintf(\ }
textcolor(7);
textbackground(0); gotoxy(x,y); }