学校的数据结构布置的作业。处理核心采用了双链表的结构。
typedef struct Line{
char text[1024];
struct Line* prev;
struct Line* next;
}line;
采用命令行操作,可完成行为单位的插入、删除、复制剪切粘贴等任务。为表对前辈的敬意,名为vimisa。读取命令的枢纽函数console()如下:
line* console(line* h){
char str[1024],*pc;
memset(str,0,1024);
line* l = h,temp,clipboard;
memset(clipboard.text,0,1024);
int a,b;
COORD pos = {23,0};
system("cls");
printS(l);
printf(">>>");
gets(str);
while(strcmp(str,"\\exit")!=0){
if(strncasecmp(str,"\\i ",3)==0){
l = r_i(l,str+3);
}
else if(strncasecmp(str,"\\d ",3)==0){
a = 1;
b = sscanf(str+2,"%d",&a);
if(b) l = r_d(l,a);
else printf("INPROPER FORMAT\n");
}
else if(strncasecmp(str,"\\e ",3)==0){
l = r_e(l,str+3);
}
else if(strncasecmp(str,"\\m ",3)==0){
a = 1;
b = sscanf(str+2,"%d",&a);
if(b) l = r_m(l,a);
else printf("INPROPER FORMAT\n");
}
else if(strncasecmp(str,"\\c ",3)==0){
l = copy(l,&clipboard);
}
else if(strncasecmp(str,"\\x ",3)==0){
l = cut(l,&clipboard);
}
else if(strncasecmp(str,"\\v ",3)==0){
l = paste(l,&clipboard);
}
else if(strncasecmp(str,"\\in ",4)==0){
l = i_e(l);
}
else if(strncasecmp(str,"\\b ",3)==0){
l->prev->text[strlen(l->prev->text)-1] = ' ';
strcat(str,"\n");
strcat(l->prev->text,str+3);
}
else if(strncasecmp(str,"\\h ",3)==0){
system("cls");
printP(readF("help.txt"),999);
system("pause");
}
else{
l = r_e(l,str);
}
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
memset(str,0,1024);
system("cls");
printS(l);
printf("\n>>>");
gets(str);
}
return h;
}
在程序内,也可以键入"\h "来 查看帮助文档。支持的命令入下图所示。
使用"\in "进入,本编辑器支持行内细节编辑,但目前对汉字仍会有bug。汉字只能稳定地支持整行操作。行内编辑界面仍然采用命令操作。
可以视作一个缺陷,本编辑器的光标移动只能采用命令而不支持方向键。用"\m 5","\m -5","\r 5","\l 3"等命令实现。
Vimisa支持终端调用,在将vimisa.exe和help.txt放入用户文件夹或配置环境变量后可以采用"vimisa [filename]" 的方式打开文本文件。
代码全文如下。
//
// Created by Misappon on 2022/10/22.
//
#include
#include
#include
#include "stdlib.h"
#include "conio.h"
#include
#include
#define RSHOWLINES 10
typedef struct Line{
char text[1024];
struct Line* prev;
struct Line* next;
}line;
void gotoxy(short x, short y) {
COORD coord = {x, y};
//COORD是Windows API中定义的一种结构体类型,表示控制台屏幕上的坐标。
//上面语句是定义了COORD类型的变量coord,并以形参x和y进行初始化。
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
//GetStdHandle(STD_OUTPUT_HANDLE); 获取控制台输出句柄
//然后用SetConsoleCursorPosition设置控制台(cmd)光标位置
}
line* i_e(line* l);
line* cnclEntr(line* l,char str[1024], char* pc);
line* initLine(){
line* l = malloc(sizeof (line));
l->prev = NULL;
l->next = NULL;
memset(l->text,0,1024);
return l;
}
line* readF(const char path[1024]){
FILE* fp = fopen(path,"r");
line *l,*h;
l = malloc(sizeof (line));
l->prev = NULL;
l->next = NULL;
memset(l->text,0,1024);
h = l;
// char* str = malloc(1024*sizeof (char));
while (feof(fp) == 0){
fgets(l->text,1024,fp);
l->next = malloc(sizeof (line));
// printf("%s",l->text);
memset(l->next->text,0,1024);
l->next->prev = l;
l->next->next = NULL;
l = l->next;
}
l->prev->next=NULL;
free(l);
fclose(fp);
return h;
}
void printP(line* h,int n_hl){
line* l = h;
for(int i=0;l;i++){
if(i==n_hl){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
}
else{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}
printf("%s",l->text); // 红色字体,绿色背景
l = l->next;
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}
void printS(line* focus){//s for section
line* l = focus;
int j,swi=0;
for(j=0;jprev;j++){
l = l->prev;
}
for(int i=0;l&&i<1+j+RSHOWLINES;i++){
if(i==j||(swi==0&&l->next==NULL)){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
swi=1;
}
else{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}
printf("%s",l->text);
l = l->next;
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}
line* r_m(line* focus,int n){
int s = abs(n)/n;
for(int i=0;i!=n;i+=s) {
if(n<0) {
if(focus->prev==NULL) break;
focus = focus->prev;
}
else{
if(focus->next==NULL) break;
focus = focus->next;
}
}
return focus;
}
line* r_d(line* focus,int n){
line* med,*fo=focus;
for(int i;iprev==NULL){
med = fo->next;
}
else if(focus->next==NULL){
med = fo->prev;
}
else {
med = fo->prev;
}
if(fo->prev) fo->prev->next = fo->next;
if(fo->next) fo->next->prev = fo->prev;
free(fo);
fo = fo->next;
}
return med;
}
line* r_e(line* focus,char text[1024]){//e for edit
strcat(text,"\n");
strcpy(focus->text,text);
if(focus->next) focus = focus->next;
else{
focus->next = (line*)malloc(sizeof(line));
focus->next->prev = focus;
focus->next->next = NULL;
memset(focus->next->text,0,1024);
focus = focus->next;
}
return focus;
}
line* r_i(line* focus,char text[1024]){
line* med = malloc(sizeof(line));
if(focus->next){
focus->next->prev = med;
med->next = focus->next;
}
else{
focus->next = med;
med->next = NULL;
}
med->prev = focus;
focus->next = med;
r_e(med,text);
return med;
}
line* cut(line* l,line* clipboard){
clipboard->prev = NULL;
clipboard->next = NULL;
strcpy(clipboard->text,l->text);
l = r_d(l,1);
return l;
}
line* copy(line* l,line* clipboard){
clipboard->prev = NULL;
clipboard->next = NULL;
strcpy(clipboard->text,l->text);
return l;
}
line* paste(line* desti, line* clipboard){
strcpy(desti->text,clipboard->text);
return desti;
}
line* console(line* h){
char str[1024],*pc;
memset(str,0,1024);
line* l = h,temp,clipboard;
memset(clipboard.text,0,1024);
int a,b;
COORD pos = {23,0};
system("cls");
printS(l);
printf(">>>");
gets(str);
while(strcmp(str,"\\exit")!=0){
if(strncasecmp(str,"\\i ",3)==0){
l = r_i(l,str+3);
}
else if(strncasecmp(str,"\\d ",3)==0){
a = 1;
b = sscanf(str+2,"%d",&a);
if(b) l = r_d(l,a);
else printf("INPROPER FORMAT\n");
}
else if(strncasecmp(str,"\\e ",3)==0){
l = r_e(l,str+3);
}
else if(strncasecmp(str,"\\m ",3)==0){
a = 1;
b = sscanf(str+2,"%d",&a);
if(b) l = r_m(l,a);
else printf("INPROPER FORMAT\n");
}
else if(strncasecmp(str,"\\c ",3)==0){
l = copy(l,&clipboard);
}
else if(strncasecmp(str,"\\x ",3)==0){
l = cut(l,&clipboard);
}
else if(strncasecmp(str,"\\v ",3)==0){
l = paste(l,&clipboard);
}
else if(strncasecmp(str,"\\in ",4)==0){
l = i_e(l);
}
else if(strncasecmp(str,"\\b ",3)==0){
l->prev->text[strlen(l->prev->text)-1] = ' ';
strcat(str,"\n");
strcat(l->prev->text,str+3);
}
else if(strncasecmp(str,"\\h ",3)==0){
system("cls");
printP(readF("help.txt"),999);
system("pause");
}
else{
l = r_e(l,str);
}
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
memset(str,0,1024);
system("cls");
printS(l);
printf("\n>>>");
gets(str);
}
return h;
}
void saveF(char path[1024],line* head){
FILE* fp = fopen(path,"w");
line* l = head;
while(l){
fprintf(fp,"%s",l->text);
l = l->next;
}
}
line* cnclEntr(line* l,char str[1024], char* pc){
l = r_e(l,str);
return l;
}
line* i_e(line* l){//Line Internal Edit
int a=1,b,n=0,i,m=strlen(l->text),swi=1;
char str[1024],str1[1024],c;
line* temp;
memset(str,0,1024);
while(1){
system("cls");
for(i=0;l->text[i];i++){
if(i == n) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
else SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
putchar(l->text[i]);
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
printf("\n \r>>>");
memset(str,0,1024);
c = getche();
if(c == '\\'){
gets(str);
if(strncasecmp(str,"r ",2)==0){
b = sscanf(str+2,"%d",&a);
for(int i=0;l->text[n+1]&&i=0?n-a:0;
}
else if(strncasecmp(str,"d ",2)==0){
sscanf(str+2,"%d",&a);
strncpy(l->text+n,l->text+n+a,strlen(l->text));
}
else if(strncasecmp(str,"i ",2)==0){
swi = 0;
memset(str1,0,1024);
strcpy(str1,l->text+n);
strcpy(l->text+n,str+2);
strcat(l->text,str1);
}
else if(strncasecmp(str,"h ",2)==0){
temp = readF("help.txt");
printP(temp,0);
system("pause");
}
else if(strncasecmp(str," ",1)==0){//q for quit
break;
}
else{
// strcpy(l->text+n,str);
b = strlen(str);
for(i=n;itext[i] = str[i-n];
n += b;
}
}
else{
l->text[n++] = c;
}
}
if(strlen(l->text)>m && swi) strcat(l->text,"\n");
return l;
}
int main(int argc,char *argv[]){
FILE* fp;
char str[1024] = {0},str1[1024] = {0};
if(argc<2){
printf("FILE NAME\n>>>");
gets(str);
fp = fopen(str,"r");
if(!fp) fopen(str,"w");
fclose(fp);
line *h = readF(str);
h = console(h);
printf("SAVE AS\n>>>");
memset(str1,0,1024);
gets(str1);
if(strcmp(str1,"")==0);
else if(strcmp(str1,"-")==0) saveF(str,h);
else saveF(str1,h);
}
else{
fp = fopen(argv[1],"r");
if(!fp) fopen(argv[1],"w");
fclose(fp);
line *h = readF(argv[1]);
h = console(h);
printf("SAVE AS\n>>>");
memset(str,0,1024);
gets(str1);
if(strcmp(str1,"")==0);
else if(strcmp(str1,"-")==0) saveF(argv[1],h);
else saveF(str1,h);
}
return 0;
}