Чтение онлайн

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

cout << pat

<< "Не является корректным регулярным выражением\n";

exit(1);

}

cout << "Введите строки:\n";

string line; // входной буфер

int lineno = 0;

while (getline(cin,line)) {

++lineno;

smatch matches;

if (regex_search(line, matches, pattern)) {

cout << "
строка " << lineno << ": " << line << '\n';

for (int i = 0; i<matches.size; ++i)

cout << "\tmatches[" << i << "]: "

<< matches[i] << '\n';

}

else

cout << "не соответствует \n";

}

}

ПОПРОБУЙТЕ

Запустите эту программу и попробуйте применить ее для проверки нескольких шаблонов, например abc, x.*x, ( .* ), \([^)]*\) и \ w+\w+(Jr\.) ?.

23.9. Сравнение регулярных выражений

Регулярные выражения в основном используются в двух ситуациях.

Поиск строки, соответствующей регулярному выражению в (произвольно длинном) потоке данных, — функция

regex_search
ищет этот шаблон как подстроку в потоке.

Сравнение регулярного выражения со строкой (заданного размера) — функция

regex_match
ищет полное соответствие шаблона и строки.

Одним из примеров является поиск почтовых индексов в разделе 23.6. Рассмотрим извлечение данных из следующей таблицы.

Эта совершенно типичная и не очень сложная таблица (количество учеников в 2007 году в средней школе, в которой учился Бьярне Страуструп) извлечена с веб страницы, на которой она выглядела именно так, как нам нужно.

• Содержит числовые поля.

• Содержит символьные поля в строках, понятных только людям, знающим контекст, из которого извлечена таблица. (В данном случае ее могут понять только люди, знающие датский язык.)

• Символьные строки содержат пробелы.

• Поля отделены друг от друга разделителем, роль которого в данном случае играет символ табуляции.

Мы назвали эту таблицу совершенно типичной и не очень сложной, но следует иметь в виду, что одна тонкость в ней все же скрывается: на самом деле мы не можем различить пробелы и знаки табуляции; эту проблему читателям придется устранить самостоятельно.

Проиллюстрируем использование регулярных выражения для решения следующих задач.

• Убедимся, что таблица сформирована правильно (т.е. каждая строка имеет правильное количество полей).

• Убедимся, что суммы подсчитаны правильно (в последней строке содержатся суммы чисел по столбцам).

Если мы сможем это сделать, то сможем сделать почти все! Например, мы смогли бы создать новую таблицу, в которой строки, имеющие одинаковые первые цифры (например, годы: первый класс должен иметь номер 1),
объединены или проверить, увеличивается или уменьшается количество студентов с годами (см. упр. 10-11).

Для того чтобы проанализировать эту таблицу, нам нужны два шаблона: для заголовка и для остальных строк.

regex header( "^[\\w ]+( [\\w ]+)*$");

regex row( "^[\\w ]+(\\d+)(\\d+)(\\d+)$");

Помните, мы хвалили синтаксис регулярных выражений за лаконичность и полезность, а не за легкость освоения новичками? На самом деле регулярные выражения имеют заслуженную репутацию языка только для письма (write-only language). Начнем с заголовка. Поскольку он не содержит никаких числовых данных, мы могли бы просто отбросить первую строку, но — исключительно для приобретения опыта — попробуем провести ее структурный анализ. Она содержит четыре словарных поля (буквенно-цифровых поля”, разделенных знаками табуляции). Эти поля могут содержать пробелы, поэтому мы не можем просто использовать управляющий символ
\w
, чтобы задать эти символы. Вместо этого мы используем выражение
[\w]
, т.е. словообразующий символ (букву, цифру или знак подчеркивания) или пробел. Один или несколько словообразующих символов задается выражением
[\w]+
. Мы хотим найти тот из них, который стоит в начале строки, поэтому пишем выражение
^[\w ]+
. “Шапочка” (
^
) означает “начало строки”. Каждое из оставшихся полей можно выразить как знак табуляции, за которым следуют некие слова:
([\w]+)
. До конца строки их может быть сколько угодно:
([\w]+)*$
. Знак доллара (
$
) означает “конец строки”. Теперь напишем строковый литерал на языке C++ и получим дополнительные обратные косые черты.

"^[\\w ]+( [\\w ]+)*$"

Мы не можем проверить, что знак табуляции действительно является таковым, но в данном случае он раскрывается в ходе набора текста и распознается сам.

Приступим к самой интересной части упражнения: к шаблону для строк, из которых мы хотим извлекать числовые данные. Первое поле вновь имеет шаблон

^[\w]+
. За ним следуют ровно три числовых поля, перед каждым из которых стоит знак табуляции: (
\d+
), следовательно, получаем следующий шаблон:

^[\w ]+( \d+)(\d+)(\d+)$

После его вставки в строковый литерал он превращается в такую строку:

"^[\\w ]+(\\d+)(\\d+)(\\d+)$"

Теперь мы сделали все, что требовалось. Сначала проверим, правильно ли сформирована таблица.

int main

{

ifstream in("table.txt"); // входной файл

if (!in) error("Нет входного файла\n");

string line; // буфер ввода

int lineno = 0;

regex header( "^[\\w ]+( [\\w ]+)*$"); // строка заголовка

regex row("^[\\w]+(\\d+)(\\d+)(\\d+)$"); // строка данных

if (getline(in,line)) { // проверяем строку заголовка

smatch matches;

if (!regex_match(line,matches,header))

error("Нет заголовка");

Поделиться:
Популярные книги

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

Газлайтер. Том 15

Володин Григорий Григорьевич
15. История Телепата
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Газлайтер. Том 15

Идеальный мир для Лекаря 5

Сапфир Олег
5. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 5

Вперед в прошлое 6

Ратманов Денис
6. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 6

Идеальный мир для Лекаря 13

Сапфир Олег
13. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 13

Менталист. Конфронтация

Еслер Андрей
2. Выиграть у времени
Фантастика:
боевая фантастика
6.90
рейтинг книги
Менталист. Конфронтация

Земная жена на экспорт

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Земная жена на экспорт

Ищу жену для своего мужа

Кат Зозо
Любовные романы:
любовно-фантастические романы
6.17
рейтинг книги
Ищу жену для своего мужа

Девятый

Каменистый Артем
1. Девятый
Фантастика:
боевая фантастика
попаданцы
9.15
рейтинг книги
Девятый

Бальмануг. (Не) Любовница 2

Лашина Полина
4. Мир Десяти
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Бальмануг. (Не) Любовница 2

Подаренная чёрному дракону

Лунёва Мария
Любовные романы:
любовно-фантастические романы
7.07
рейтинг книги
Подаренная чёрному дракону

Лорд Системы 7

Токсик Саша
7. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 7

Чехов. Книга 3

Гоблин (MeXXanik)
3. Адвокат Чехов
Фантастика:
альтернативная история
5.00
рейтинг книги
Чехов. Книга 3

Семья. Измена. Развод

Высоцкая Мария Николаевна
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Семья. Измена. Развод