29 myname = argv[0];
30 while ((c = getopt(argc, argv, ":iE")) != -1) {
31 switch (c) {
32 case 'i':
33 ignore_case = 1;
34 break;
35 case 'E':
36 extended = 1;
37 break;
38 case '?':
39 usage();
40 break;
41 }
42 }
43
44 if (optind == argc) /* проверка исправности */
45 usage();
46
47 compile_pattern(argv[optind]); /* компилировать шаблон */
48 if (errors) /* ошибка компиляции */
49 return 1;
50 else
51 optind++;
В строке 29 устанавливается значение myname
pattern, compilе_раttern() увеличивает значение errors, если была проблема. (Соединение функций посредством глобальной переменной, как здесь, обычно считается плохой манерой. Для небольших программ, подобным этой, это сойдет, но для более крупных программ такое сопряжение может стать проблемой.) Если не было ошибок, строка 51 увеличивает значение optind так, что оставшиеся аргументы представляют файлы для обработки.53 if (optind == argc) /* файлов нет, по умолчанию stdin */
54 process("standard input", stdin);
55 else {
56 /* цикл с файлами */
57 for (i = optind; i < argc; i++) {
58 if (strcmp(argv[i], "-") == 0)
59 process("standard input", stdin);
60 else if ((fp = fopen(argv[i], "r")) != NULL) {
61 process(argv[i], fp);
62 fclose(fp);
63 } else {
64 fprintf(stderr, "%s: %s: could not open: %s\n",
65 argv[0], argv[i], strerror(errno));
66 errors++;
67 }
68 }
69 }
70
71 regfree(&pattern);
72 return errors != 0;
73 }
Строки 53–69 обрабатывают файлы, отыскивая соответствующие шаблону строки. Строки 53–54 обрабатывают случай, когда файлы не указаны: программа читает со стандартного ввода. В противном случае, строки 57–68 обрабатывают в цикле файлы. Строка 58 обрабатывает особый случай '-
75 /* compile_pattern --- компиляция шаблона */
76
77 void compile_pattern(const char *pat)
78 {
79 int flags = REG_NOSUB; /* информация о месте совпадения не требуется */
80 int ret;
81 #define MSGBUFSIZE 512 /* произвольно */
82 char error[MSGBUFSIZE];
83
84 if (ignore_case)
85 flags |= REG_ICASE;
86 if (extended)
87 flags |= REG_EXTENDED;
88
89 ret = regcomp(&pattern, pat, flags);
90 if (ret != 0) {
91 (void)regerror(ret, &pattern, error, sizeof error);
92 fprintf(stderr, "%s: pattern '%s': %s\n", myname, pat, error);
93 errors++;
94 }
95 }
Строки 75–95 определяют функцию compile_pattern()
REG_NOSUB в flags, поскольку нам нужно знать лишь «подходит ли строка?», а не «где в строке располагается подходящий текст?»Строки 84-85 добавляют дополнительные флаги в соответствии с опциями командной строки. Строка 89 компилирует шаблон, а строки 90–94 сообщают о возникших ошибках
97 /* process --- читает строки текста и сопоставляет их с шаблоном */
98
99 void process(const char *name, FILE *fp)
100 {
101 char *buf = NULL;
102 size_t size = 0;
103 char error[MSGBUFSIZE];
104 int ret;
105
106 while (getline(&buf, &size, fp) != -1) {
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT