auto pos = it->prefix().length(); //
pos = pos > 40 ? pos - 40 : 0; //
cout << it->prefix().str().substr(pos) //
<< "\n\t\t>>> " << it->str () << " <<<\n" //
//
<< it->suffix().str().substr(0, 40) //
<< endl;
}
Сам цикл работает, как и прежде. Изменился процесс в цикле for
, представленный на рис. 17.2.
Рис. 17.2. Объект класса smatch
, представляющий некое соответствие
Здесь происходит вызов функции prefix()
, возвращающий объект класса ssub_match
, представляющий часть строки file
перед текущим соответствием. Чтобы выяснить, сколько символов находится в части строки file
перед соответствием, вызовем функцию length()
для этого объекта класса ssub_match
. Затем скорректируем значение pos
так, чтобы оно было индексом 40-го символа от конца префикса. Если у префикса меньше 40 символов, устанавливаем pos
в 0, означая, что выведен весь префикс. Функция substr()
(см. раздел 9.5.1) используется для вывода от данной позиции до конца префикса.
После вывода символов, предшествующих соответствию, выводится само соответствие с некоторым дополнительным оформлением, чтобы соответствующее слово выделилось в выводе. После вывода соответствующей части выводится до 40 следующих после соответствия символов строки file
.
Упражнение 17.17. Измените свою программу так, чтобы она находила все слова в исходной последовательности, нарушающие правило "
Упражнение 17.18. Пересмотрите свою программу так, чтобы игнорировать слова, содержащие сочетание "ei", но не являющиеся ошибочными, такие как "albeit" и "neighbor".
17.3.3. Использование подвыражений
Схема в регулярном выражении зачастую содержит одно или несколько
Например, в схеме для поиска соответствий расширений файлов языка С++ (см. раздел 16.1.2) круглые скобки используются для группировки возможных расширений. Каждый раз, когда альтернативы группируются с использованием круглых скобок, одновременно объявляется, что эти альтернативы формируют подвыражение. Это выражение можно переписать так, чтобы оно предоставило доступ к имени файла, являющемуся той частью схемы, которая предшествует точке:
//
//
//
regex r("([[:alnum:]]+)\\.(cpp|схх|cc)$", regex::icase);
Теперь в схеме два заключенных в скобки подвыражения:
• ([[:alnum:]]+)
— представляет последовательность из одного или нескольких символов;
• (cpp|схх|cc)
— представляет расширения файлов.
Теперь программу из раздела 16.1.2 можно переписать так (изменив оператора вывода), чтобы выводить только имя файла:
if (regex_search(filename, results, r))
cout << results.str(1) << endl; //
В первоначальной программе для поиска схемы r
в строке filename
использовался вызов функции regex_search()
, а также объект results
класса smatch
для содержания результата поиска соответствия. Если вызов успешен, выводится результат. Но в этой программе выводится str(1)
, т.е. соответствие для первого подвыражения.
Кроме информации об общем соответствии, объекты соответствия предоставляют доступ к каждому соответствию подвыражению в схеме. К соответствиям подвыражению обращаются по позиции. Первое соответствие подвыражению, расположенное в позиции 0, представляет соответствие для всей схемы. После него располагается каждое подвыражение. Следовательно, имя файла, являющееся первым подвыражением в схеме, находится в позиции 1, а расширение файла — в позиции 2.
Например, если именем файла будет foo.cpp
, то results.str(0)
содержит строку "foo.cpp"
; results.str(1)
— "foo"
, a results.str(2) — "cpp"
.
В этой программе требуется часть имени перед точкой, что является первым подвыражением, поэтому следует вывести results.str(1)
.