本程序要求完成一个简易文本编辑器,能够完成文本的录入、编辑、删除、查找,并能够完成文件的存取。

在文本编辑软件中把用户输入的所有文本内容作为一个字符串。虽然各种文本编辑软件的功能有强弱差别,但是基本操作都包括串的输入、修改、删除(包括整行删除和一行中的子串删除)、查找、输出等。通过分析,系统应该包括以下功能:

  1. 具有简单的文字或图形菜单界面
  2. 能实现串或文本块的查找、替换、删除、插入、移动操作。
  3. 能实现文本文件的存盘和读取功能。
  4. 具有友好的界面和较强的容错能力
  • 设计思路
  1. 采用的逻辑结构

文本编辑器主要是针对文本进行编辑,文本的操作就是对字符的操作。文本编辑器可以从行、列两个方向进行编辑。

每一行可以看成一个线性表,线性表是一种线性结构,线性结构的特点是数据元素之间为线性关系,数据元素“一个接一个的排列”。在一个线性表中数据元素的类型是相同的,由于每一行可以存储的最大字数是相同的,行方向所有线性表的最大长度可以设置成相同的。行与行之间的关系也可以看成一个线性表。

2.采用的存储结构

线性表的存储分为两种:顺序存储和链式存储。

顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各元素,用这种存储形式存储的线性表称为顺序表。在程序设计语言中,一维数组在内存中占用的存储空间就是一组连续的存储区域,因此,用一维数组来表示顺序表的数据存储区域是再合适不过的。

链式存储是通过-组任意的存储单元来存储线性表中的数据元素的,为建立数据元系之间的线性关系,对每个数据元素除了存放数据元素自身的信息之外,还需要和一起存放其后继或前驱所在的存储单元的地址,这两部分信息组成一个“结点”,每个元素都如此。存放数据元素信息的称为数据域,存放其前驱或后继地址的称为指针域。只有一个存储单元地址的为单链表,有两个存储单元地址的为双链表。

考虑到实际的功能需求,每行的线性表可以用顺序存储方式,每个字符是一个节点。用数组的长度表示本行可以输入的最大字符。行与行之间的线性表采用双链表存储,每个节点包括四个区域,一个指针域prior指向上一行,一个指针域next指向下一行,一个数据域num是行号,一个数据域是本行的字符数组。程序以行和列标识文本位置,行采用双向链表存储行信息,用数组下标标识列信息,从而能够准确定位字符位置,然后进行查找、替换、插入、块移动、删除等多种操作。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_LEN 100
#define NOT_FOUND -1
//定义行结构体:
struct line
{char text[MAX_LEN];  //本行文本int num;  //行号struct line *next; //指向下一个行的指针struct line *prior; //指向前一个行的指针
};
int lnum;
struct line *start;        //指向线性表中第一行的指针
struct line *last;     //指向线性表中最后一行的指针
struct line *find(int);    //查找指定行是否存在
void patchup(int, int);    //对当前行以后的每行的行号加1或
void delete_text(int);     //删除一行文字
void list();   //显示文件的全部内容
void save();   //保存文件
void load();   //打开文件,初始化线性表
void insert(char str[], int linenum, int position); //插入文字到一行的中间
void printline(int linenum);   //打印一行文字
void deletestr(int linenum, int position, int lenth); //删除一个字符串
int findstr(char * to_find);  //查找字符串
int menu_select();        //显示主菜单
int menu_select_insert();//显示插入功能子菜单
int menu_select_delete();//显示删除功能子菜单
int menu_select_print(); //显示打印功能子菜单
int menu_select_move();  //显示移动功能子菜单
void enter(int linenum); //插入一行文字
void enter_empty(int linenum); //插入一个空白行
//下列函数是系统主函数,提供系统主界面,通过选择项转入执行插入、删除、查存盘、读人文件等功能的界面。
int main(void)
{char str[MAX_LEN];int choice;int linenum = 1;int number = 0;start = NULL;last = NULL;load(); //打开文件,初始化线性表do{choice = menu_select();switch (choice){case 1:        //执行插入功能    choice = menu_select_insert();//显示插入子菜单switch (choice){case 1:   //插入一行printf("\t行号:");scanf("%d", &linenum);enter(linenum);break;case 2:  //插入到指定行的指定列printf("输入插入位置一行号:");scanf("%d", &linenum);printf("输入插入位置-列号:");scanf("%d", &number);printf("要插入的字符串:");scanf("%s", str);insert(str, linenum, number);break;case 3:   //退出插入break;}break;case 2:           //执行删除功能choice = menu_select_delete();  // 删除子菜单switch (choice){case 1:   //删除指定行printf("\t行号:");scanf("%d", &linenum);break;case 2:   //删除指定的字符串printf("要删除的字符串:");scanf("%s", str);number = findstr(str);if (number == NOT_FOUND)printf("没有找到");elsedeletestr(lnum, number, strlen(str));break;case 3:   //退出删除break;}break;case 3:      //执行显示功能choice = menu_select_print(); //显示子菜单switch (choice)   //显示指定行{case 1:printf("\t行号:");scanf("%d", &linenum);printline(linenum);break;case 2:       //显示全部list();break;case 3:      //退出显示break;}break;case 4:          //执行查找功能printf("输入想要查找的字符串:");scanf("%s", str);number = findstr(str);if (number == NOT_FOUND)printf("没有找到");elseprintf("要查找的字符串所在行号:%d,列号:%d\n", lnum, number + 1);break;case 5:      //执行替换功能printf("输入被替换的字符串:");scanf("%s", str);number = findstr(str);if (number == NOT_FOUND)printf("没有找到");else{deletestr(lnum, number, strlen(str));printf("要替换的字符串:");scanf("%s", str);insert(str, lnum, number + 1);}break;case 6:     //执行移动功能choice = menu_select_move();   //移动子菜单switch (choice){case 1:   // 向下移动一行printf("输人要移动的字符串所在行号:");scanf("%d", &linenum);enter_empty(linenum);break;case 2:   //向上移动一行printf("输入要移动的字符串所在行号:");scanf("%d", &linenum);delete_text(linenum - 1);break;case 3:   //向右移动一列printf("输人要移动的字符串所在行号:");scanf("%d", &linenum);printf("输入要移动的字符串所在列号:");scanf("%d", &number);str[0] = ' ';str[1] = '\0';insert(str, linenum, number);break;case 4:   //向左移动printf("输入要移动的字符串所在行号:");scanf("%d", &linenum);printf("输入要移动的字符串所在列号:");scanf("%d", &number);if (number <= 0)printf("该列不存在");elsedeletestr(linenum, number - 2, 1);break;case 5:   //退出移动break;}break;case 7:      //执行存盘功能save();break;case 8:        //执行读入文件功能load();break;case 9:      //执行退出功能exit(0);break;}} while (1);return 0;
}
//下列函数是主菜单功能的提示界面,其功能是说明主菜单中选项
int menu_select()
{int c;printf("\n\t\t1.插入\n");printf("\t\t2.删除\n");printf("\t\t3.显示\n");printf("\t\t4.查找\n");printf("\t\t5.替换\n");printf("\t\t6.移动\n");printf("\t\t7.文件存盘\n");printf("\t\t8.装入文件\n");printf("\t\t9.退出\n");do{printf("\n\n\t\t请按数字选择:");scanf("%d", &c);} while (!(c >= 1 && c <= 9));return(c);
}//下列函数是插入子菜单功能的提示界面,其功能是说明在插入菜单下选项的含义。
int menu_select_insert()
{int c;printf("\n\t\t1.插入一行文字\n");printf("\t\t2.插入一段文字\n");printf("\t\t3.返回上级菜单\n");do{printf("\n\n\t\t请按数字选择:");scanf("%d", &c);} while (!(c >= 1 && c <= 3));return(c);
}
//下列函数是删除子菜单功能的提示界面,其功能是说明在删除子菜单下选项的含义。
int menu_select_delete()
{int c;printf("\n\t\t1.删除一行文字\n");printf("\t\t2.删除一段文字\n");printf("\t\t3.返回上级菜单\n");do{printf("\n\n\t\t请按数字选择:");scanf("%d", &c);} while (!(c >= 1 && c <= 3));return(c);
}
//下列函数是显示子菜单功能的提示界面,其功能是说明在显示子菜单下选项的含义
int menu_select_print()
{int c;printf("\n\t\t1.显示一行\n");printf("\t\t2.全部显示\n");printf("\t\t3.返回上级菜单\n");do{printf("\n\n\t\t请按数字选择:");scanf("%d", &c);}while(!(c >= 1 && c <= 3));return(c);
}
//下列函数是移动子菜单功能的提示界面,其功能是说明在移动子菜单下选项的含义
int menu_select_move()
{int c;printf("\n\t\t1.向下移动一行\n");printf("\t\t2.向上移动一行\n");printf("\t\t3.向右移动一列\n");printf("\t\t4.向左移动一列\n");printf("\t\t5.返回上级菜单\n");do{printf("\n\n\t\t请按数字选择:");scanf("%d", &c);} while (!(c >= 1 && c <= 5));return(c);
}
//下列函数的功能是在指定的行号 linenum处插入一行文字。
void enter(int linenum)
{struct line * info, * q, * p;p = start;q = NULL;while (p && p->num != linenum) //找到插入行{q = p;p = p->next;}if (p == NULL && (q->num + 1) != linenum)  //指定行不存在,不能插入{printf("输入的行号不存在");}else // 指定行存在,进行插入{info = (struct line *)malloc(sizeof(struct line));printf("输入要输入的字符串");scanf("%s", info->text);info->num = linenum;if (linenum == 1)  //插入在第一行{info->next = p;p->prior = info;info->prior = NULL;start = info;}else if (q->num != linenum)  //插入在最后一行{q->next = info;info->next = p;info->prior = q;}else     //插入在其他行{q->next = info;info->next = p;p->prior = info;info->prior = q;}while (p)   //如果不是插入在最后一行,插入行后面的行号都加1{p->num = p->num + 1;p = p->next;}}
}//下列函数是为其他功能提供的一个辅助函数,它的功能是当文本内容插在文件中间时
//其下面的内容的行号必须增加1,而删除时,被删除的文本后面的行号必减1.
void patchup(int n, int incr)
{struct line *i;i = find(n);i = i->next;while (i){i->num = i->num + incr;i = i->next;}
}
//下列函数的功能是在指定行处插入一个空白行。
void enter_empty(int linenum)
{struct line *info, *p;info = (struct line *)malloc(sizeof(struct line));if (!info){printf("\t!内存不够!\n");exit(0);}info->text[0] = ' ';info->text[1] = '\0';info->num = linenum;if (find(linenum))    //如果要插人的行号存在,则进行插入{p = start;if (linenum == 1)    //插入在首行{info->next = p;start = info;info->prior = NULL;p->prior = info;}else  //插入在其他行{while (p->next->num != linenum)p = p->next;info->next = p->next;p->next->prior = info;p->next = info;info->prior = p;}patchup(linenum, 1);}elseprintf("该行不存在");
}//下列函数的功能是插入文字到一行的中间。要是插入位置和现有位置中间有间隔,会补全空格
void insert(char str[], int linenum, int position)
{struct line * info;int len, i;int lenth;char rest_str[MAX_LEN], nostr[2] = { " " };info = start;while (info && info->num != linenum)   //查询要插入的行{info = info->next;}if (info == NULL)printf("不存在该行!\n");else if (position < 0)printf("不存在该列!\n");else    //如果行和列都存在,则进行插入{lenth = strlen(info->text);if (lenth < position)    //插入列大于本行文件列数{len = position - lenth - 1;for (i = 0; i < len; i++)strcat(info->text, nostr);   //将空余的部分插入空格符strcat(info->text, str);    //插入字符到列的未尾}else   //插入列在本行文字的中间{strcpy(rest_str, &info->text[position - 1]);strcpy(&info->text[position - 1], str);strcat(info->text, rest_str);}}
}//下列函数的功能是删除指定行、指定位置、长度为 lenth的一段文字。
void deletestr(int linenum, int position, int lenth)
{struct line * info;char rest_str[MAX_LEN];info = find(linenum);if (info == NULL)printf("该行没有字符!n");else{if (strlen(info->text) <= (position + lenth))  //本行的字符长度<=待删除的列号+删除长度,直接在当前位置插入'\0'info->text[position] = '\0';else{strcpy(rest_str, &info->text[position + lenth]);strcpy(&info->text[position], rest_str);}}
}
//下列函数的功能是删除指定行号 lineup的文字。
void delete_text(int linenum)
{struct line * info, *p;info = start;while ((info->num < linenum) && info)info = info->next;if (info->next == NULL)printf("该行不存在");else{p = info->next;if (start == info) //如果删除的是第一行{start = info->next;if (start)  //如果删除后,不为空start->prior = NULL;else  //删除后为空last = NULL;}else{info->prior->next = info->next;  //指定行的上一行指向指定行的下一行if (info != last) //如果不是最后一行info->next->prior = info->prior;  //修改其下一行的指向头的指针 else  //如果是最后一行,修改尾指针last = info->prior;}free(info);while (p){p->num = p->num - 1;p = p->next;}}
}
//下列函数的功能是查找一段文字。
int findstr(char * to_find)
{struct line * info;int i = 0, find_len, found = 0, position;char substring[MAX_LEN];info = start;lnum = 0;  //匹配到的行号find_len = strlen(to_find);while (info && !found)   //查询{i = 0;  //行间循环while (!found && (i <= strlen(info->text) - find_len))  //行内查找循环{strcpy(substring, &info->text[i], find_len);substring[find_len] = '\0';if (strcmp(substring, to_find) == 0){found = 1;lnum = info->num;}else++i;}info = info->next;}if (found)  //查找成功position = i;else   //查找不成功position = NOT_FOUND;return(position);
}
//下列函数的功能是查找指定行,如果查找成功返回结点所在的行指针。
struct line * find(int linenum)
{struct line * info;info = start;while (info){if (linenum != info->num)info = info->next;elsebreak;}return (info);
}//下列函数的功能是显示指定行
void printline(int linenum)
{struct line *info;info = find(linenum);if (info)printf("%d:%s\n", info->num, info->text);elseprintf("该行不存在");
}
//下列函数的功能是显示线性表中的所有文本
void list()
{struct line * info;info = start;while (info){printf("%d:%s\n", info->num, info->text);info = info->next;}printf("\n\n");
}
//下列函数的功能是把线性表中的所有文字保存到文件中
void save()
{struct line    * info;char * p;FILE * fp;if ((fp = fopen("D:\\text.txt", "w")) == NULL){printf("\t文件打不开!n");exit(0);}printf("\t正在存入文件!\n");info = start;while (info){p = info->text;while (*p)putc(*p++, fp);putc('\n', fp);info = info->next;}fclose(fp);
}
//下列函数的功能是把文本文件中的内容读入到线性表中。
void load()
{struct line *info, *temp;  //info指向当前行,temp指向info的前驱行char c;FILE *fp;  //文件指针int inct, i;  //行计数器temp = NULL;if ((fp = fopen("D:\\text.txt", "r")) == NULL){printf("\t文件打不开!\n");exit(0);}printf("\n\t正装入文件!\n");start = (struct line*)malloc(sizeof(struct line)); //动态生成一行的结点空间info = start;inct = 1;while ((c = fgetc(fp)) != EOF){i = 0;info->text[i] = c;i++;while ((c = fgetc(fp)) != '\n')  //从文件中读取一行字符到线性表中,文件中每一行以\n为结束标{info->text[i] = c;i++;}info->text[i] = '\0';  //线性表中每行末尾的结束标志info->num = inct++;  //行号和计数器都加1info->next = (struct line*)malloc(sizeof(struct line));if (!info->next){printf("\n\t内存已经用完!");exit(0);}info->prior = temp;temp = info;info = info->next;}temp->next = NULL;last = temp;free(info);start->prior = NULL;fclose(fp);
}

c语言实现简易文本编辑器相关推荐

  1. C语言程序设计-简易文本编辑器

    第一部分:引言 简易文本编辑器是一个面向用户的系统服务程序,广泛用于源程序的输入.删除.替换.查找.修改等一系列操作,甚至用于报刊和书籍的编辑排版以及办公室的公文书信的起草和润色,是一个比较实用的应用 ...

  2. c语言课程设计文本编辑器实验报告6,C课程设计简易文本编辑器.doc

    C课程设计简易文本编辑器 目录 第一章 课程设计目的和要求1 1.1课程设计的目1 1.2 基本要求1 第二章 课程设计任务内容2 2.1 设计背景2 2.2简易文本编辑器设计内容2 第三章 详细设计 ...

  3. 基于 c++ 语言的简易 vim 编辑器

    问题描述 现要求你设计出一个基于 c/c++ 语言的简易 vim 编辑器. 基本要求 在命令行模式下,实现 vim 的一些基本功能,必须实现的功能包括以下内容: 编辑器有两个模式,normal 和 i ...

  4. java简单文本编译器_java -简易文本编辑器

    import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** * Title:java ...

  5. VB顺序文件案例:简易文本编辑器

    文章目录 一.顺序文件概述 二.案例演示 - 简易文本编辑器 (一)运行效果 (二)实现步骤 1.用户界面设计 (1)创建标准EXE工程 (2)添加一个文本框 (3)添加四个按钮 (4)添加一个公用对 ...

  6. Java swing 简易文本编辑器

    1.介绍几个相关的网址 精通Java Swing程序设计 BeautyEye社区 2.主要功能 tab页能够关闭(快捷键:ctrl+w,鼠标点击x) JMuneItem和Button快键键的几种绑定 ...

  7. [汇编] 汇编语言实现简易文本编辑器(光标移动、上卷和退格删除)

    https://blog.csdn.net/NK_test/article/details/46045201 汇编实现的一个简易的文本编辑器,代码中有详细的注释. 思路和细节: (1) 在屏幕中央初始 ...

  8. [转][汇编] 汇编语言实现简易文本编辑器(光标移动、上卷和退格删除)

    汇编实现的一个简易的文本编辑器,代码中有详细的注释. 思路和细节: (1) 在屏幕中央初始化一片面积,并且定位光标,利用16号中断0号功能分别在ah,al中存储扫描码和ascii码,由此进行功能键的判 ...

  9. python基础项目实战-简易文本编辑器

    在这里我简单编写了文本编辑器的部分功能,还有一些没有完善,感兴趣的友友们可以自己尝试完善后面的功能.文本编辑器的基本设计: 一.界面设计 1.标题 2.菜单栏 3.文本编辑区 4.滚动条 5.鼠标快右 ...

最新文章

  1. 开源 免费 java CMS - FreeCMS1.2-标签 mailList
  2. sqlserver yml配置文件
  3. 如何编写高性能的C#代码(一)
  4. Everyday is an Opportunity
  5. linux 7查内核,查看CentOS7内核版本及发行版本
  6. 3蛋白wb_老司机手把手教你选WB内参
  7. python中怎样创建字典内建函数_python中常用的字典内建函数
  8. wscript.exe无法打开vbs_如何恶搞朋友的电脑?超简单的vbs代码
  9. 国内外大厂集结,远程办公大考成绩单发布!
  10. Xna游戏编辑器开发(WinForm内嵌Xna)
  11. SpringMVC路径配置
  12. 一个很不错的远程软件TeamViewer
  13. Nucleus SE RTOS 初始化和启动
  14. USACO-Fractions to Decimals
  15. Python:numpy array数据去头去尾巴
  16. java+SpringBoot+HTML+Mysq基于微信小程序的掌上博物馆游览
  17. 周鸿袆:教你打造十页完美商业计划书
  18. Android App Bundle 自动打包原理
  19. Python数据分析从入门到精通视频教程
  20. 【GitHubDailyShare】在 Linux 上无缝运行 macOS 系统软件

热门文章

  1. 吉大计算机学院林丛郁,吉林大学07院士候选人分析
  2. NSIS之Modern UI
  3. JetBrains旗下软件通用激活方法
  4. 电子病历与HIS的区别以及发展前途
  5. Pascal's Triangle (LeetCode) 帕斯卡三角或者叫杨辉三角----动态规划和memoization
  6. 【愚公系列】2023年02月 WMS智能仓储系统-004.内存缓存的使用
  7. 8个很有用的PHP安全函数,你知道几个?
  8. 仿牛客网社区项目 全栈总结
  9. thinkphp不会识别unsigned int数据类型,会导致sql执行错误
  10. QLineEdit 中使用QML原生虚拟键盘Qt5VirtualKeyboard