一個簡單的文本編譯器,簡單文本編譯器
花了幾天,從沒有思路到寫完。因為是第一次寫這種命令交互式的,所以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
這是我寫的代碼:
![](https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017012110341379.gif)
![]()
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 int modified = 0; /* 修改標志 */
17 int last; /* 文本的最後一行,沒有內容 */
18 void Edit(), Replace(), Insert(), Delete(), Quit();
19 void (*comfunc[])() = {Edit, Replace, Insert, Delete, Quit}; /* 函數指針數組 */
20 void call();
21
22 int main(void)
23 {
24 call();
25 return 0;
26 }
27
28 void call()
29 {
30 int j = 0;
31 char ch;
32 last = 0;
33
34 while (1)
35 {
36 j = 0;
37 printf("Input a command: [e,r,i,d,q]\n");
38
39 /* bug1 */
40 //ch = ' ';
41 //fflush(stdin);
42 while ((ch = fgetc(stdin)) != '\n') /* 輸入命令 */
43 {
44 buffer[j] = ch;
45 j++;
46 }
47 buffer[j] = '\0';
48
49 for (chpt = buffer; *chpt == ' ' || *chpt == '\t'; chpt++) /* 跳過空白符 */
50 ;
51
52 if (*chpt == '\0')
53 {
54 printf("Doesn't input any command\n");
55 continue;
56 }
57
58 for (j = 0; command[j] != *chpt && command[j] != '\0'; j++) /* 獲取命令的序號 */
59 if (command[j] == '\0')
60 {
61 printf("Cannot find command.\n");
62 continue;
63 }
64 chpt++; /* 指向參數 */
65 (*comfunc[j/2])(); /* 執行相應的函數 */
66
67 printf("The text is:\n");
68 for (j = 0; j < last; j++) /* 輸出text的內容 */
69 fputs(Line[j], stdout);
70 }
71
72 }
73
74 void Edit()
75 {
76 int i;
77 FILE *fp_temp; /* 臨時的文件指針 */
78
79 i = sscanf(chpt, "%s", filename); /* sscnaf函數返回值是參數的個數,參數應當只有一個 */
80
81 if (i != 1) /* 沒有輸入文件名或者輸入超過一個文件名 */
82 {
83 printf("not input filename or more than 1 file, please input filename again:\n");
84 scanf(" %s", filename);
85 }
86
87 /* 打開指定文件,沒有就創建新的文件 */
88 if ((fp_temp = fopen(filename, "r")) == NULL) /* 沒有這個文件,則創建新的文件 */
89 {
90 if ((fp_temp = fopen(filename, "w")) == NULL)/* 創建新的文件 */
91 {
92 printf("Cannot create a new file");
93 return;
94 }
95 fclose(fp_temp);
96 if ((fp_temp = fopen(filename, "r")) == NULL)
97 {
98 printf("Cannot read");
99 return;
100 }
101 }
102
103 i = 0;
104 while ((fgets(buffer, CHMAX, fp_temp)) == buffer) /* 不用擔心buffer越界問題,因為接下來沒有使用到buffer */
105 {
106 Line[i] = (char *)malloc((strlen(buffer)) + 1);
107 strcpy(Line[i], buffer);
108 i++;
109 }
110 last = i;
111
112 fclose(fp_temp);
113 modified = 1; /* 已修改 */
114 }
115
116 void Replace()
117 {
118 int i, k, m, n; /* 將k行正文替換到第m行和第n行中 */
119
120 if (modified != 1)
121 {
122 printf("Did not open a file.\n");
123 return;
124 }
125
126 i = sscanf(chpt, "%d%d%d", &k, &m, &n);
127 if (i != 3 || m < 0 || n < 0 || k < 0 || m > n || n > last || k > last)
128 {
129 printf("format error\n");
130 return;
131 }
132
133
134 if (k != (n-m+1))
135 {
136 printf("error number of lines replaced.\n");
137 return;
138 }
139
140 /* 寫k行正文 */
141 printf("Please input %d line words:\n", k);
142
143 /* 替換 */
144 for (i = 0; i < k; i++)
145 {
146 free(Line[m+i-1]);
147 fgets(buffer, CHMAX, stdin);
148 Line[m+i-1] = (char *)malloc(strlen(buffer) + 1);
149 strcpy(Line[m+i-1], buffer);
150 }
151
152 modified = 1;
153 }
154
155 void Insert()
156 {
157 int i, k, m; /* 將k行正文插入到原始正文第m行之後 */
158
159
160 if (modified != 1) /* Edit最後修改modified標志 */
161 {
162 printf("Did not open a file.\n");
163 return;
164 }
165
166 i = sscanf(chpt, "%d%d", &k, &m);
167
168 if (i != 2 || k < 0 || m < 0 || last + k >= LINEMAX)
169 {
170 printf("format error.\n");
171 return;
172 }
173
174 /* 寫k行正文 */
175 printf("Please input %d line words:\n", k);
176
177 /* 先將原文的第m+1行開始都向後移k行 */
178 for (i = last-1; i > m-1; i--)
179 {
180 Line[i+k] = Line[i];/* 向後移k行 */
181 }
182
183 /* 再將中間的k行補上 */
184 for (i = 0; i < k; i++)
185 {
186 fgets(buffer, CHMAX, stdin);
187 Line[m+i] = (char *)malloc(strlen(buffer) + 1);
188 strcpy(Line[m+i], buffer);
189 }
190
191 last += k; /* 給原來的last增加k行 */
192 modified = 1; /* 已修改 */
193 }
194
195 void Delete()
196 {
197 int i, j, m, n; /* 刪去原始正文的第m行到第n行內容 */
198
199 if (modified != 1)
200 {
201 printf("Did not open a filen\n");
202 return;
203 }
204
205 i = sscanf(chpt, "%d%d", &m, &n);
206 if (i != 2 || m < 0 || n < 0 || m >n || n > last)
207 {
208 printf("format error\n");
209 return;
210 }
211
212 /* 先刪去,再移位 */
213 for (i = 0; i < (n-m+1); i++)
214 free(Line[m+i-1]);
215 for(i = n, j = 0; i < last; i++, j++)
216 Line[m+j-1] = Line[i];
217 last -= (n-m+1);
218
219 modified = 1;
220 }
221
222 void Quit()
223 {
224 int i;
225 char flag;
226 FILE *fp_temp;
227
228 printf("Save? y/n:");
229 scanf(" %c", &flag);
230
231 if (flag == 'Y' || flag == 'y')
232 {
233 if ((fp_temp = fopen(filename, "w")) == NULL)
234 {
235 printf("Cannot open a file");
236 exit(1);
237 }
238 for (i = 0; i < last; i++)
239 fputs(Line[i], fp_temp);
240 printf("save successfully!\n");
241 }
242 else
243 ;
244 exit(0);
245
246 }
View Code
下面給出運行結果:
![](https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017012110341319.png)
![](https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017012110341341.png)
ps:最好都是每一行都會有回車鍵,因為fgets函數是指定字符數的。具體看代碼就應該知道了。
有興趣的同學可以改進!