Литмир - Электронная Библиотека
A
A

if (boost::regex_search(line, matches, pat))

Мы используем реализацию библиотеки

Boost.Regex
, которая скоро станет частью стандартной библиотеки. Для того чтобы использовать библиотеку
Boost.Regex
, ее необходимо инсталлировать. Для того чтобы показать, какие возможности относятся к библиотеке
Boost.Regex
, мы явно указываем пространство имен
boost
в качестве квалификатора, т.е.
boost::regex
.

Вернемся к регулярным выражениям! Рассмотрим следующий фрагмент кода:

boost::regex pat ("\\w{2}\\s*\\d{5}(–\\d{4})?");

cout << "шаблон: " << pat << '\n';

Здесь мы сначала определили шаблон

pat
(типа
regex
), а затем вывели его на печать. Обратите внимание на то, что мы написали:

\\w{2}\\s*\\d{5}(–\\d{4})?

Если бы вы запустили программу, то увидели бы на экране следующую строку:

pattern: \w{2}\s*\d{5}(–\d{4})?

В строковых литералах языка С++ обратная косая черта означает управляющий символ (раздел A.2.4), поэтому вместо одной обратной косой черты (\) в литеральной строке необходимо написать две (\\).

 

Программирование. Принципы и практика использования C++ Исправленное издание - _002.png
 Шаблон типа
regex
на самом деле является разновидностью объекта класса
string
, поэтому мы можем вывести его на печать с помощью оператора
<<
. Класс
regex
— это не просто разновидность класса
string
, но его довольно сложный механизм сопоставления шаблонов, созданных при инициализации объекта класса
regex
(или при выполнении оператора присваивания), выходит за рамки рассмотрения нашей книги. Однако, поскольку мы инициализировали объект класса
regex
шаблоном почтовых кодов, можем применить его к каждой строке нашего файла.

boost::smatch matches;

if (boost::regex_search(line, matches, pat))

  cout << lineno << ": " << matches[0] << '\n';

 

Программирование. Принципы и практика использования C++ Исправленное издание - _002.png
 Функция
regex_search(line, matches, pat)
ищет в строке
line
любое соответствие регулярному выражению, хранящемуся в объекте
pat
, и если она находит какое-либо соответствие, то сохраняет его в объекте
matches
. Естественно, если соответствие не обнаружено, функция
regex_search(line, matches, pat)
возвращает значение
false
.

Переменная

matches
имеет тип
smatch
. Буква
s
означает “sub.” По существу, тип
smatch
представляет собой вектор частичных совпадений. Первый элемент
matches[0]
представляет собой полное совпадение. Мы можем интерпретировать элемент
matches[i]
как строку, если
i<matches.size()
. Итак, если для данного регулярного выражения максимальное количество частичных шаблонов равно
N
, выполняется условие
matches.size()==N+1
.

 

Программирование. Принципы и практика использования C++ Исправленное издание - _002.png
 Что такое частичный шаблон (sub-pattern)? Можно просто сказать: “Все, что заключено в скобки внутри шаблона”. Глядя на шаблон "\\w{2}\\s*\\d{5}(–\\d{4})?", мы видим скобки вокруг четырехзначного кода ZIP. Таким образом, мы видим только один частичный шаблон, т.е.
matches.size()==2
. Кроме того, можно догадаться, что у нас есть простой доступ к этим четырем последним цифрам. Рассмотрим пример.

while (getline(in,line)) {

  boost::smatch matches;

  if (boost::regex_search(line, matches, pat)) {

    cout << lineno << ": " << matches[0] << '\n'; // полное

                                                  // совпадение

    if (1<matches.size() && matches[1].matched)

      cout << "\t: " << matches[1] << '\n'; // частичное

                                            // совпадение

  }

}

Строго говоря, мы не обязаны проверять выражение

1<matches.size()
, поскольку уже рассмотрели шаблон, но к этому нас подталкивает легкая паранойя (поскольку мы экспериментируем с разными шаблонами, хранящимися в объекте
pat
, и не все они содержат только один частичный шаблон). Мы можем проверить, обнаружен ли частичный шаблон, просматривая его член
matched
, в данном случае
matches[1].matched
. Нас интересует следующая ситуация: если значение
matches[i].matched
равно
false
, то частичные шаблоны
matches[i]
, у которых нет соответствия, выводятся как пустые строки. Аналогично, если частичный шаблон не существует, например
matches[17]
для приведенного выше шаблона, то он рассматривается как шаблон, у которого нет соответствия.

Мы применили нашу программу к файлу, содержащему следующие строки:

address TX77845

ffff tx 77843 asasasaa

ggg TX3456–23456

howdy

zzz TX23456–3456sss ggg TX33456–1234

cvzcv TX77845–1234 sdsas

xxxTx77845xxx

TX12345–123456

Результат приведен ниже.

pattern: "\w{2}\s*\d{5}(–\d{4})?"

1: TX77845

2: tx 77843

5: TX23456–3456

: –3456

6: TX77845–1234

: –1234

7: Tx77845

8: TX12345–1234

324
{"b":"847443","o":1}