оптимизируй этот код, сделай лаконичнее, точнее и эффективнее. Не меняя структуру функционал d, [17.11.2024 10:26] #include #include #include #include #include #define MAX_PATTERN_LENGTH 9999999 #define MAX_LINE_LENGTH 10000 typedef struct flag { int e; int i; int v; int c; int l; int n; int filecount; } flags; typedef struct patterns { char **patterns; int count; } patterns_t; int s21_parser(int argc, char *argv[], flags *flag, patterns_t *pat); void process_file(const char *filename, flags flag, patterns_t pat); int match_pattern(const char *line, patterns_t pat, flags flag); void print_match(const char *filename, int line_num, const char *line, flags flag); void free_patterns(patterns_t *pat); int main (int argc, char *argv[]) { flags flag = {0, 0, 0, 0, 0, 0, 0}; patterns_t pat = {NULL, 0}; int ret = 0; int start = s21_parser(argc, argv, &flag, &pat); if (start == -1) { ret = 1; } else { if (flag.filecount == 0) { process_file("", flag, pat); } else { for (int i = start; i < argc; i++) { process_file(argv[i], flag, pat); } } } free_patterns(&pat); return ret; } int s21_parser(int argc, char *argv[], flags *flag, patterns_t *pat) { int option; int ret = 0; pat->patterns = malloc(sizeof(char*) * argc); if (!pat->patterns) { fprintf(stderr, "Memory allocation error\n"); ret = -1; } if (ret == 0) { pat->count = 0; while ((option = getopt(argc, argv, "e:ivcln")) != -1) { switch (option) { case 'e': flag->e = 1; pat->patterns[pat->count++] = strdup(optarg); break; case 'i': flag->i = 1; break; case 'v': flag->v = 1; break; case 'c': flag->c = 1; break; case 'l': flag->l = 1; break; case 'n': flag->n = 1; break; case '?': fprintf(stderr, "Unknown option: -%c\n", optopt); ret = -1; break; default: break; } if (ret == -1) { break; } } } if (ret == 0 && !flag->e) { if (optind < argc) { pat->patterns[pat->count++] = strdup(argv[optind++]); } else { fprintf(stderr, "No pattern provided.\n"); ret = -1; } } if (ret == 0) { flag->filecount = argc - optind; } else { free_patterns(pat); } if (ret == -1) { return -1; } else { return optind; } } void free_patterns(patterns_t *pat) { if (pat->patterns) { for (int i = 0; i < pat->count; i++) { free(pat->patterns[i]); } free(pat->patterns); pat->patterns = NULL; } } int match_pattern(const char *line, patterns_t pat, flags flag) { int match = 0; regex_t regex; int reti; int cflags = REG_EXTENDED; if (flag.i) { cflags |= REG_ICASE; } for (int i = 0; i < pat.count; i++) { reti = regcomp(®ex, pat.patterns[i], cflags); if (reti) { fprintf(stderr, "Could not compile regex: %s\n", pat.patterns[i]); continue; } reti = regexec(®ex, line, 0, NULL, 0); if (!reti) { match = 1; } else if (reti == REG_NOMATCH) { } else { char errbuf[100]; regerror(reti, ®ex, errbuf, sizeof(errbuf)); fprintf(stderr, "Regex match failed: %s\n", errbuf); } regfree(®ex); if (match) break; } if (flag.v) return !match; else return match; } void print_match(const char *filename, int line_num, const char *line, flags d, [17.11.2024 10:26] flag) { if (flag.filecount > 1 && filename[0] != '\0') { printf("%s:", filename); } if (flag.n) { printf("%d:", line_num); } printf("%s", line); if (line[strlen(line) - 1] != '\n') { printf("\n"); } } void process_file(const char *filename, flags flag, patterns_t pat) { FILE *file; int need_processing = 1; if (filename[0] == '\0') { file = stdin; } else { file = fopen(filename, "r"); if (!file) { fprintf(stderr, "s21_grep: %s: Cannot open file\n", filename); need_processing = 0; } } if (need_processing) { char *line = NULL; size_t len = 0; ssize_t read; int count = 0; int matched = 0; int line_num = 0; while ((read = getline(&line, &len, file)) != -1) { line_num++; matched = match_pattern(line, pat, flag); if (matched) { count++; if (!flag.c && !flag.l) { print_match(filename, line_num, line, flag); } } } if (flag.c) { if (flag.filecount > 1 && filename[0] != '\0') { printf("%s:%d\n", filename, count); } else { printf("%d\n", count); } } if (flag.l && count > 0 && filename[0] != '\0') { printf("%s\n", filename); } free(line); } if (file != stdin) { fclose(file); } }