C语言实例解析精粹学习笔记——39(简单的文本编辑器)
实例说明:
编辑一个简单的单行文本编辑器,编辑命令有以下几种:(E、Q、R、I、D)
只有自己在完全空白的情况下编写出来的程序,才是真正自己会的程序,现在所做的,不过是程序的搬运工,把书上的程序搬到网上,不过是添加了几句注释而已。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define MAXLEN 80 //所处理文本一行最大字符个数 6 #define MAXLINE 200 //所处理文本最大行数 7 8 char buffer[MAXLEN]; //用来存储命令行输入的命令,以及命令所带的参数 9 char fname[120]; //用来存储所处理文件的文件名 10 char *lineptr[MAXLINE]; //行指针 11 FILE *fp; //文件指针 12 void edit(),replace(),insert(),delete(),quit(); //函数声明,具体的函数定义在后面 13 char comch[] = "EeRrIiDdQq"; //命令符 14 void(*comfun[])() = {edit,replace,insert,delete,quit}; //对应处理函数 15 int modified=0; //正文修改标志 16 int last; //当前正文行数 17 char *chpt; //输入命令行字符指针 18 19 20 int main() 21 { 22 int j; 23 last = 0; 24 25 while(1) 26 { 27 printf("\nInput a command:[e,r,i,d,q].\n"); 28 gets(buffer); //读入命令行 29 for(chpt=buffer; *chpt==' '||*chpt=='\t'; chpt++); //掠过空白符 30 if(*chpt=='\0') continue; //空行重新输入 31 for(j=0; comch[j]!='\0'&&comch[j]!=*chpt; j++); //查找命令符对应的处理函数 32 if(comch[j]=='\0') continue; //非法命令符 33 chpt++; //掠过命令符,指向参数 34 (*comfun[j/2])(); //执行对应的函数 35 fprintf(stdout,"The text is :\n"); 36 for(j=0; j<last; j++) //显示正文文本 37 fputs(lineptr[j],stdout); 38 } 39 return 0; 40 } 41 42 //==================================================================================== 43 //函数名称:void quit() 44 //函数功能:结束编辑 45 //对应命令:q/Q 46 //入口参数:无 47 //出口参数:无 48 //==================================================================================== 49 void quit() 50 { 51 int c; 52 if(modified) //判断正文是否被修改 53 { 54 printf("Save?(y/n)"); 55 while(!(((c=getchar())>='a'&&c<='z')||(c>='A'&&c<='Z'))); //判断输入是否为合法字符 56 if(c=='y'||c=='Y') 57 save(fname); 58 } 59 for(c=0; c<last; c++) 60 free(lineptr[c]); //释放内存 61 exit(0); 62 } 63 64 //==================================================================================== 65 //函数名称:void insert() 66 //函数功能:将I/i命令后继的K行文本插入到原始正文第M行之后 67 //入口参数:无 68 //出口参数:无 69 //命令格式: 70 //I K M 71 //K行正文 72 //==================================================================================== 73 void insert() 74 { 75 int k,m,i; 76 sscanf(chpt, "%d%d", &k, &m); 77 if(m<0||m>last||last+k>=MAXLINE) //判断插入文本位置是否正确 78 { 79 printf("Error!\n"); 80 return; 81 } 82 for(i=last; i>m; i--) //后继行向后移 83 lineptr[i+k-1] = lineptr[i-1]; 84 for(i=0; i<k; i++) //读入k行正文,并插入 85 { 86 fgets(buffer, MAXLEN, stdin); 87 lineptr[m+i] = (char *)malloc(strlen(buffer)+1); 88 strcpy(lineptr[m+1],buffer); 89 } 90 last += k; //修改正文行数 91 modified = 1; //标明正文已被修改 92 } 93 94 //==================================================================================== 95 //函数名称:void delete() 96 //函数功能:将原始正文中第M行至第N行的正文内容删去 97 //入口参数:无 98 //出口参数:无 99 //命令格式: 100 //D M N 101 //==================================================================================== 102 void delete() 103 { 104 int i,j,m,n; 105 sscanf(chpt, "%d%d", &m,&n); 106 if(m<=0||m>last||n<m) //检查参数合理性 107 { 108 printf("Error!\n"); 109 return; 110 } 111 if(n>last) 112 n = last; //修正参数 113 for(i=m; i<=n; i++) //删除正文 114 free(lineptr[i-1]); 115 for(i=m,j<n+1; j<=last; i++,j++) //将原文的N行之后的文本前移 116 lineptr[i-1] = lineptr[j-1]; 117 last = i-1; 118 modified = 1; 119 } 120 121 //==================================================================================== 122 //函数名称:void replace() 123 //函数功能:用R命令后继的K行正文替代原始正文中的M行到N行的正文内容 124 //入口参数:无 125 //出口参数:无 126 //命令格式: 127 //R K M N 128 //K行正文 129 //==================================================================================== 130 void replace() 131 { 132 int k,m,n,i,j; 133 sscanf(chpt,"%d%d%d",&k,&m,&n); /* 读入参数 */ 134 if(m<=0||m>last||n<m||last-(n-m+1)+k>=MAXLINE) /* 检查参数合理性 */ 135 { 136 printf("Error!\n"); 137 return; 138 } 139 /* 先完成删除 */ 140 if(n>last) 141 n=last; /* 修正参数 */ 142 for(i=m;i<=n;i++) /* 删除正文 */ 143 free(lineptr[i-1]); 144 for(i=m,j=n+1;j<=last;i++,j++) //文本前移 145 lineptr[i-1]=lineptr[j-1]; 146 last=i-1; 147 /* 以下完成插入 */ 148 for(i=last;i>=m;i--) 149 lineptr[i+k-1]=lineptr[i-1]; 150 for(i=0;i<k;i++) 151 { 152 fgets(buffer,MAXLEN,stdin); 153 lineptr[m+i-1]=(char *)malloc(strlen(buffer)+1); 154 strcpy(lineptr[m+i-1],buffer); 155 } 156 last+=k; /* 修正正文行数 */ 157 modified=1; /* 正文被修改 */ 158 } 159 160 //==================================================================================== 161 //函数名称:void save(char *fname) 162 //函数功能:用来保存文本 163 //入口参数:char *fname 164 //出口参数:无 165 //==================================================================================== 166 void save(char *fname) /* 保存文件 */ 167 { 168 int i; 169 FILE *fp; 170 if((fp=fopen(fname,"w"))==NULL) 171 { 172 fprintf(stderr,"Can't open %s.\n",fname); 173 exit(1); 174 } 175 for(i=0;i<last;i++) 176 { 177 fputs(lineptr[i],fp); 178 free(lineptr[i]); 179 } 180 fclose(fp); 181 } 182 183 //==================================================================================== 184 //函数名称:void edit() 185 //函数功能:指定所要编辑的文本 186 //入口参数:无 187 //出口参数:无 188 //==================================================================================== 189 void edit() /* 编辑命令 */ 190 { 191 int i; 192 FILE *fp; 193 i=sscanf(chpt,"%s",fname); /* 读入文件名 */ 194 if(i!=1) 195 { 196 printf("Enter file name.\n"); 197 scanf("%s",fname); 198 } 199 if((fp=fopen(fname,"r"))==NULL) /* 读打开 */ 200 { 201 fp=fopen(fname,"w"); /* 如不存在,则创建文件 */ 202 fclose(fp); 203 fp=fopen(fname,"r"); /* 重新读打开 */ 204 } 205 i=0; 206 while(fgets(buffer,MAXLEN,fp)==buffer) 207 { 208 lineptr[i]=(char *)malloc(strlen(buffer)+1); 209 strcpy(lineptr[i++],buffer); 210 } 211 fclose(fp); 212 last=i; 213 }