首页 > 代码库 > 一个简单的文本编译器

一个简单的文本编译器

花了几天,从没有思路到写完。因为是第一次写这种命令交互式的,所以bug会很多。

格式:E/e:指定要编辑的文件

   Q/q:结束编辑

   R/r(用r命令后继的k行正文代替原始正文中的m行到n行)

    R  k m n

     k行正文

   I/i(将i命令后继的k行正文插入到原始正文第m行之后)

    I k m

     k行正文

   D/d(将原始正文中的第m行到第n行的正文内容删除)

    D m n

这是我写的代码:

技术分享
  1 /* 实现简单的文本编辑器 */  2 /* bug1:先按e,再按文件名,循环后ch还是等于‘\n‘ */  3 /* bug2:插入函数中,要是正文的一行最后不是回车的话,则插入的第一行会在所插的那一行上面,没有分开 */  4 #include <stdio.h>  5 #include <stdlib.h>  6 #include <string.h>  7   8 #define    CHMAX    80    /* 一行最多80个字符 */  9 #define    LINEMAX    200    /* 最多允许200行 */ 10  11 char command[] = "EeRrIiDdQq";    /* 可选择的命令 */ 12 char buffer[CHMAX];            /* 输入的缓冲区 */ 13 char *Line[LINEMAX];    /* 行指针,用来输入一行 */ 14 char *chpt;    /* 获取命令及参数的字符指针 */ 15 char filename[256];    /* 输入的文件名 */ 16 FILE *fp;    /* 用于输入到文件的文件指针 */ 17 int modified = 0;    /* 修改标志 */ 18 int last;    /* 文本的最后一行,没有内容 */ 19 void Edit(), Replace(), Insert(), Delete(), Quit(); 20 void (*comfunc[])() = {Edit, Replace, Insert, Delete, Quit};    /* 函数指针数组 */ 21 void call(); 22  23 int main(void) 24 { 25     call(); 26     return 0; 27 } 28  29 void call() 30 { 31     int    j = 0; 32     char    ch; 33     last = 0; 34  35     while (1) 36     { 37         j = 0; 38         printf("Input a command: [e,r,i,d,q]\n"); 39  40         /* bug1 */ 41         //ch = ‘ ‘; 42         //fflush(stdin); 43         while ((ch = fgetc(stdin)) != \n)        /* 输入命令 */ 44         { 45             buffer[j] = ch; 46             j++; 47         } 48         buffer[j] = \0; 49          50         for (chpt = buffer; *chpt ==   || *chpt == \t; chpt++)    /* 跳过空白符 */ 51             ; 52          53         if (*chpt == \0) 54         { 55             printf("Doesn‘t input any command\n"); 56             continue; 57         } 58      59         for (j = 0; command[j] != *chpt && command[j] != \0; j++)    /* 获取命令的序号 */ 60             if (command[j] == \0) 61             { 62                 printf("Cannot find command.\n"); 63                 continue; 64             } 65         chpt++;            /* 指向参数 */ 66         (*comfunc[j/2])();    /* 执行相应的函数 */ 67  68         printf("The text is:\n"); 69         for (j = 0; j < last; j++)    /* 输出text的内容 */ 70             fputs(Line[j], stdout); 71     } 72  73 } 74  75 void Edit() 76 { 77     int    i; 78     FILE    *fp_temp;    /* 临时的文件指针 */ 79  80     i = sscanf(chpt, "%s", filename);    /* sscnaf函数返回值是参数的个数,参数应当只有一个 */ 81  82     if (i != 1)    /* 没有输入文件名或者输入超过一个文件名 */ 83     { 84         printf("not input filename or more than 1 file, please input filename again:\n"); 85         scanf(" %s", filename); 86     } 87  88     /* 打开指定文件,没有就创建新的文件 */ 89     if ((fp_temp = fopen(filename, "r")) == NULL)    /* 没有这个文件,则创建新的文件 */ 90     { 91         if ((fp_temp = fopen(filename, "w")) == NULL)/*  创建新的文件 */ 92         { 93             printf("Cannot create a new file"); 94             return; 95         } 96         fclose(fp_temp); 97         if ((fp_temp = fopen(filename, "r")) == NULL) 98         { 99             printf("Cannot read");100             return;101         }102     }103                                                                                                                    104     i = 0;105     while ((fgets(buffer, CHMAX, fp_temp)) == buffer)    /* 不用担心buffer越界问题,因为接下来没有使用到buffer */106     {107         Line[i] = (char *)malloc((strlen(buffer)) + 1);108         strcpy(Line[i], buffer);109         i++;110     }111     last = i;    112     113     fclose(fp_temp);114     modified = 1;    /* 已修改 */115 }116 117 void Replace()118 {119     int    i, k, m, n;    /* 将k行正文替换到第m行和第n行中 */120     121     if (modified != 1)122     {123         printf("Did not open a file.\n");124         return;125     }126 127     i = sscanf(chpt, "%d%d%d", &k, &m, &n);128     if (i != 3 || m < 0 || n < 0 || k < 0 || m > n || n > last || k > last)129     {130         printf("format error\n");131         return;132     }133 134     135     if (k != (n-m+1))136     {137         printf("error number of lines replaced.\n");138         return;139     }140 141     /* 写k行正文 */142     printf("Please input %d line words:\n", k);143 144     /* 替换 */145     for (i = 0; i < k; i++)146     {147         free(Line[m+i-1]);148         fgets(buffer, CHMAX, stdin);149         Line[m+i-1] = (char *)malloc(strlen(buffer) + 1);150         strcpy(Line[m+i-1], buffer);151     }152         153     modified = 1;154 }155 156 void Insert()157 {158     int    i, k, m;    /* 将k行正文插入到原始正文第m行之后 */159     160 161     if (modified != 1)    /* Edit最后修改modified标志 */162     {163         printf("Did not open a file.\n");164         return;165     }166     167     i = sscanf(chpt, "%d%d", &k, &m);168     169     if (i != 2 || k < 0 || m < 0 || last + k >= LINEMAX)170     {171         printf("format error.\n");172         return;173     }174 175     /* 写k行正文 */176     printf("Please input %d line words:\n", k);177 178     /* 先将原文的第m+1行开始都向后移k行 */179     for (i = last-1; i > m-1; i--)180     {    181         Line[i+k] = Line[i];/* 向后移k行 */182     }183     184     /* 再将中间的k行补上 */185     for (i = 0; i < k; i++)186     {187         fgets(buffer, CHMAX, stdin);188         Line[m+i] = (char *)malloc(strlen(buffer) + 1);189         strcpy(Line[m+i], buffer);190     }191     192     last += k;    /* 给原来的last增加k行 */193     modified = 1;    /* 已修改 */194 }195 196 void Delete()197 {198     int    i, j, m, n;    /* 删去原始正文的第m行到第n行内容 */199 200     if (modified != 1)201     {202         printf("Did not open a filen\n");203         return;204     }205     206     i = sscanf(chpt, "%d%d", &m, &n);207     if (i != 2 || m < 0 || n < 0 || m >n || n > last)208     {209         printf("format error\n");210         return;211     }212 213     /* 先删去,再移位 */214     for (i = 0; i < (n-m+1); i++)215         free(Line[m+i-1]);216     for(i = n, j = 0; i < last; i++, j++)217         Line[m+j-1] = Line[i];218     last -= (n-m+1);219 220     modified = 1;221 }222 223 void Quit()224 {225     int    i;226     char    flag;227     FILE    *fp_temp;228 229     printf("Save? y/n:");    230     scanf(" %c", &flag);231 232     if (flag == Y || flag == y)233     {234         if ((fp_temp = fopen(filename, "w")) == NULL)235         {236             printf("Cannot open a file");237             exit(1);238         }239         for (i = 0; i < last; i++)240             fputs(Line[i], fp_temp);241         printf("save successfully!\n");242     }243     else244     ;245     exit(0);246 247 }
View Code

 

下面给出运行结果:

 技术分享

 技术分享

ps:最好都是每一行都会有回车键,因为fgets函数是指定字符数的。具体看代码就应该知道了。

有兴趣的同学可以改进!

一个简单的文本编译器