-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproj1.c
373 lines (368 loc) · 11.6 KB
/
proj1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
Proudový editor textu
autor: Daniel Pátek (xpatek08)
VUT FIT 2018
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1002 //1000 znaku + znak konce radku (\n) + znak konce retezce (\0)
void help(void);
void check_argc(int argc);
void print_curr(const char *curr);
void remove_eol(char *curr);
void replace_words(char *curr, const char *line, const char *oldW,const char *newW, int a);
int get_line(char *c);
int read_line(FILE *name, char *c);
int tree(char *curr, char *comm, FILE *name);
int get_char(char *s, int i);
int go_to(char *comm, FILE *name);
int goto_X(int a, int b, char *comm, FILE *name);
int S_replace(char *curr, char *comm);
int next(char *curr, const char *comm);
int next_count(int a, int b, char *curr);
int insert(const char *comm);
int after(char *curr, char *comm);
int before(char *curr, char *comm);
int delete_line(char *curr, const char *comm);
int main(int argc, char *argv[]){
char curr_line[MAX];
char comm[MAX];
check_argc(argc);
FILE *fr = fopen(argv[1], "r"); //otevre soubor s prikazy
if (get_line(curr_line) == 1){ //nacte prvni radek
fprintf(stderr, "Chyba vstupu ze stdin. Ukonceni programu.\n");
fclose(fr);
return -1;
}
else{
while (read_line(fr, comm) != 1){ //pokud najde prikaz, provede pomocí tree, co je treba
if (tree(curr_line, comm, fr) != 0){
fclose(fr);
return -1;
}
}
}
fclose(fr);
return 1;
}
//pomocna zprava
void help(void){
printf("Pokracujte spustenim programu s prave jednim argumentem - nazvem souboru s prikazy, napr: prikazy.txt. \nProgram slouzi jako proudovy editor textu. Pomoci ruznych prikazu radek po radku edituje vstupni text. \nSeznam prikazu: \niCONTENT(insert) - vlozi pred aktualni radek radek s obsahem CONTENT.\nbCONTENT (before) vlozi na zacatek aktualniho radku obsah CONTENT.\naCONTENT (after/append) vlozi na konec aktualniho radku obsah CONTENT.\nd (delete) - smaze aktualni radek.\ndN smaze N radku (N > 0).\nr (remove EOL) - na aktualnim radku odstrani znak konce radku.\ns PATTERN REPLACEMENT (substitute) na aktualnim radku provede substituci (nahrazeni) vyskytu retezce PATTERN za retezec REPLACEMENT. PATTERN musi byt neprazdny.\ns:PATTERN:REPLACEMENT - substituce retezce, pricemz PATTERN a REPLACEMENT mohou byt od sebe oddelene libovolnym tisknutelnym znakem.\nS:PATTERN:REPLACEMENT - stejne jako s:PATTERN:REPLACEMENT, ale nahrazuje vsechny vyskyty PATTERN.\nn (next) - posun aktualniho radku o jeden niz, tj. tiskne aktualni radek.\nnN - posun aktualniho radku o N niz. (N > 0).\nq (quit) - ukonci editaci, dalsi radky nezpracovava a ani netiskne.\ngX (goto) preskoc s aktualnim prikazem pro editaci na X-ty prikaz.\n");
exit(0);
}
//kontrola argumentu
// argument - pocet argumentu
void check_argc(int argc){
if (argc < 2) {
fprintf(stderr, "Nezadali jste zadny argument.\n");
help();
}
else if (argc > 2) {
fprintf(stderr, "Zadali jste prilis mnoho argumentu.\n");
help();
}
}
//tiskne aktualni radek
void print_curr(const char *curr){
printf("%s", curr);
}
//nacteni radku ze stdin
// argumenty - nazev stringu na ulozeni aktualniho radku
int get_line(char *c){
char buffer[MAX];
if((fgets(buffer, MAX, stdin)) != NULL){
for(unsigned int i = 0; i <= (strlen(buffer)); i++){
c[i] = buffer[i];
}
return 0;
}else{
return 1;
}
}
//nacteni radku ze souboru s prikazy
// argumenty - nazev souboru s prikazy a nazev stringu k ulozeni radku
int read_line(FILE *name, char *c){
char buffer[MAX];
if((fgets(buffer, MAX, name)) != NULL){
for(unsigned int i = 0; i <= strlen(buffer); i++){
c[i] = buffer[i];
}
return 0;
}else{
return 1;
}
}
//zjisti jaky prikaz provadet
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem, nazev souboru s prikazy
int tree(char *curr, char *comm, FILE *name){
int sym = comm[0];
switch (sym){
case 'n':
if (next(curr, comm) != 0)
return 1;
break;
case 'q':
return 1;
case 'i':
if (insert(comm) != 0)
return -1;
break;
case 'b':
if (before(curr, comm) != 0)
return -1;
break;
case 'a':
if (after(curr, comm) != 0)
return -1;
break;
case 'd':
if (delete_line(curr, comm) != 0)
return 1;
break;
case 'r':
remove_eol(curr);
break;
case 'g':
if (go_to(comm, name) != 0)
return -1;
break;
case 'S':
case 's':
if (S_replace(curr, comm) != 0)
return -1;
break;
default:
fprintf(stderr, "Prikaz %c: Nepodporovany prikaz. ", comm[0]);
return -1;
}
return 0;
}
//odstrani urcity pocet radku
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem
int delete_line(char *curr, const char *comm){
int number[3];
if ((comm[1] - '0') >= 0 && (comm[1] - '0') < 10){
unsigned int i = 1;
while (i < strlen(comm)){
if ((comm[i] - '0') >= 0 && (comm[i] - '0') < 10){
number[i] = (comm[i] - '0');
}else{
break;
}
i++;
}
if (i > 2){
int j = 0;
while (j < ((number[1]*10) + number[2])){
if (get_line(curr) != 0)
return 1;
j++;
}
}else{
int j = 0;
while (j < number[1]){
if (get_line(curr) != 0)
return 1;
j++;
}
}
}else{
if (get_line(curr) != 0)
return 1;
}
return 0;
}
//odstrani znak konce radku
// argument - nazev stringu s aktualnim radkem
void remove_eol(char *curr){
int i = 0;
while(curr[i] != '\0'){
i++;
}
curr[i-1] = '\0';
}
//vlozi text za aktualni radek
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem
int after(char *curr, char *comm){
if (strlen(comm) > 1){
memmove(comm, comm+1, strlen(comm));
int i = 0;
while(curr[i] != '\0'){
i++;
}
curr[i-1] = '\0';
strcat(curr, comm);
}else{
fprintf(stderr, "Prikaz %c: Nenalezeno slovo k napsani. \n", comm[0]);
return -1;
}
return 0;
}
//vlozi text pred aktualni radek
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem
int before(char *curr, char *comm){
if (strlen(comm) > 1){
memmove(comm, comm+1, strlen(comm));
int i = 2;
while(comm[i] != '\0'){
i++;
}
comm[i-1] = '\0';
strcat(comm, curr);
for(unsigned int i = 0; i <= (strlen(comm)); i++){
curr[i] = comm[i];
}
}else{
fprintf(stderr, "Prikaz %c: Nenalezeno slovo k napsani. \n", comm[0]);
return -1;
}
return 0;
}
//vlozi jiny radek pred aktualni radek
// argumenty - nazev stringu s aktualnim prikazem
int insert(const char *comm){
if (strlen(comm) > 1){
for(unsigned int i = 1; i < strlen(comm); i++){
putchar(comm[i]);
}
}else{
fprintf(stderr, "Prikaz %c: Nenalezeno slovo k napsani. \n", comm[0]);
return -1;
}
return 0;
}
//spocita kolikrat zahodit radek a prejde na urcity radek
// argumenty - pocet desitek radku, pocet jednotek radku, nazev stringu s aktualnim prikazem, nazev souboru s prikazy
int goto_X(int a, int b, char *comm, FILE *name){
rewind(name);
int i = 1;
while(i != ((a*10)+b)){
if (read_line(name, comm) != 0){
fprintf(stderr, "Prikaz g: Pozadovany radek neexistuje. ");
return -1;
}
i++;
}
return 0;
}
//prejde na urcity radek
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem
int next(char *curr, const char *comm){
int number[3];
if ((comm[1] - '0') >= 0 && (comm[1] - '0') < 10){
unsigned int i = 1;
while (i < strlen(comm)){
if ((comm[i] - '0') >= 0 && (comm[i] - '0') < 10){
number[i] = (comm[i] - '0');
}else{
break;
}
i++;
}
if (i > 2){
if (next_count(number[1], number[2], curr) != 0)
return 1;
}else{
if (next_count(0, number[1], curr) != 0)
return 1;
}
}else{
if (next_count(0, 1, curr) != 0)
return 1;
}
return 0;
}
//spocita kolikrat zmenit radek a provede to
// argumenty - pocet desitek radku, pocet jednotek radku, nazev stringu s aktualnim radkem
int next_count(int a, int b, char *curr){
int j = 0;
while (j < ((a*10) + b)){
print_curr(curr);
if (get_line(curr) != 0){
return 1;
}
j++;
}
return 0;
}
//prejde na urcity radek
// argumenty - nazev stringu s aktualnim prikazem, nazev souboru s prikazy
int go_to(char *comm, FILE *name){
int i = 1;
int number[3];
while(i <= 2){
if ((comm[i] - '0') > 0 && (comm[i] - '0') < 10){
number[i] = (comm[i] - '0');
}else{
break;
}
i++;
}
if (!((comm[1] - '0') > 0 && (comm[1] - '0') < 10)){
fprintf(stderr, "Prikaz %c: Nenalezeno cislo radku. \n", comm[0]);
return -1;
}else if (i < 3){
if (goto_X(0, number[1], comm, name) != 0)
return -1;
}else{
if (goto_X(number[1], number[2], comm, name) != 0)
return -1;
}
return 0;
}
//vymena patter za replacement v celem retezci
// argumenty - nazev stringu s aktualnim radkem, nazev stringu s aktualnim prikazem
int S_replace(char *curr, char *comm){
char pattern[MAX];
char replacement[MAX];
const char spacer[2] = {comm[1]};
char *token;
token = strtok(comm, spacer); // zahodí první token (S)
if ((token = strtok(NULL, spacer)) != NULL){ // importuje pattern
for(unsigned int i = 0; i <= (strlen(token)); i++){
pattern[i] = token[i];
}
}else{
fprintf(stderr, "Prikaz %c: Nenalezeno slovo k nahrazeni. \n", comm[0]);
return -1;
}
if ((token = strtok(NULL, spacer)) != NULL){ // importuje replacement
unsigned int i = 0;
for(; i <= (strlen(token)); i++){
replacement[i] = token[i];
}
replacement[i-2] = '\0';
}else{
fprintf(stderr, "Prikaz %c: Nenalezeno slovo k nahrazeni. \n", comm[0]);
return -1;
}
if (comm[0] == 'S'){
replace_words(curr, curr, pattern, replacement, -1);
}else{
replace_words(curr, curr, pattern, replacement, 1);
}
return 0;
}
//zmeni pattern za replacement
// argumenty - nazev stringu s aktualnim radkem, znovu pro kopii, nazev patternu, nazev replacementu, cislo pro rozeznani prikazu s a S
void replace_words(char *curr, const char *line, const char *oldW, const char *newW, int a){
int i = 0;
int newWlen = strlen(newW);
int oldWlen = strlen(oldW);
char result[MAX];
while (*line){
if (strstr(line, oldW) == line && ((a > 0) || (a < 0))){
strcpy(&result[i], newW);
i += newWlen;
line += oldWlen;
a--;
}
else
result[i++] = *line++;
}
result[i] = '\0';
for(unsigned int i = 0; i <= (strlen(result)); i++){
curr[i] = result[i];
}
}