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

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

Жанры

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

found = FindMatch(str,strpat);

//образец задает подстроку, начинающуюся с символа а,

//заканчивающуюся f с возможными символами b и d в середине

strpat = "a(b|d)*f"; str = "fabadddbdf";

found = FindMatch(str,strpat);

//диапазоны и escape-символы

strpat = M[X-Z]+"; str = "aXYb";

found = FindMatch(str,strpat);

strpat = @"\u005BY\x5A"; str = "aXYZb";

found = FindMatch(str,strpat);

}//TestSinglePat

Некоторые комментарии к этой процедуре.

Регулярные выражения задаются @-константами, описанными в лекции 14. Здесь они как нельзя кстати.

В первом образце используется последовательность символов \w+,

обозначающая, как следует из таблицы 15.1, непустую последовательность латиницы и цифр. В совокупности образец задает подстроку, начинающуюся символом а, за которым следуют буквы или цифры (хотя бы одна). Этот образец применяется к двум различным строкам.

В следующем образце используется символ * для обозначения итерации. В целом регулярное выражение задает строки, начинающиеся с символа а и заканчивающиеся символом f, между которыми находится возможно пустая последовательность символов из b и d.

Последующие два образца демонстрируют использование диапазонов и escape-последовательностей для представления символов, заданных кодами (в Unicode и шестнадцатиричной кодировке).

Взгляните на результаты, полученные при работе этой процедуры.

Рис. 15.1. Регулярные выражения. Поиск по образцу

Пример "чет и нечет"

Не всякий класс языков можно описать с помощью регулярных выражений. И даже тогда, когда такая возможность есть, могут потребоваться определенные усилия для корректной записи соответствующего регулярного выражения. Рассмотрим, например, язык L1 в алфавите T= {0,1}, которому принадлежат пустое слово и слова, содержащие четное число нулей и четное число единиц. В качестве другого примера рассмотрим язык L2, отличающийся от первого тем, что в нем число единиц нечетно. Оба языка можно задать регулярными выражениями, но корректная запись непроста и требует определенного навыка. Давайте запишем регулярные выражения, определяющие эти языки, и покажем, что C# справляется с проблемой их распознавания. Вот регулярное выражение, описывающее первый язык:

(00|11) * ((01|10) (00|11) * (01|10) (00|11) * )*

Дадим содержательное описание этого языка. Слова языка представляют возможно пустую последовательность из пар одинаковых символов. Далее может идти последовательность, начинающаяся и заканчивающаяся парами различающихся символов, между которыми может стоять произвольное число пар одинаковых символов. Такая группа может повторяться многократно. Регулярное выражение короче и точнее передает описываемую структуру слов языка L1.

Язык L2 описать теперь совсем просто. Его слова представляют собой единицу, окаймленную словами языка L1.

Прежде чем перейти к примеру распознавания слов языков L1 и L2, приведу процедуру FindMatches, позволяющую найти все вхождения образца в заданный текст:

void FindMatches(string str, string strpat)

{

Regex pat = new Regex(strpat);

MatchCollection matchcol =pat.Matches(str);

Console.WriteLine ("Строка = {0} \tОбразец= {1} ", str, strpat);

Console.WriteLine("Число совпадений ={0}",matchcol.Count);

foreach(Match match in matchcol)

Console.WriteLine("Index = {0} Value = {1}, Length ={2}",

match.Index,match.Value, match.Length);

}//FindMatches

Входные

аргументы у процедуры те же, что и у функции FindMatch, ищущей первое вхождение. Я не стал задавать выходных аргументов процедуры, ограничившись тем, что все результаты непосредственно выводятся на печать в самой процедуре. Выполнение процедуры, так же, как и в FindMatch, начинается с создания объекта pat класса Regex, конструктору которого передается регулярное выражение. Замечу, что класс Regex, так же, как и класс string, относится к неизменяемым (immutable) классам, поэтому для каждого нового образца нужно создавать новый объект pat.

В отличие от FindMatch, объект pat вызывает метод Matches, который определяет все вхождения подстрок, удовлетворяющих образцу, в заданный текст. Результатом выполнения метода Matches является автоматически создаваемый объект класса MatchCollection, хранящий коллекцию объектов уже известного нам класса Match, каждый из которых задает очередное вхождение. В процедуре используются свойства коллекции и ее элементов для получения в цикле по элементам коллекции нужных свойств — индекса очередного вхождения подстроки в строку, ее длины и значения.

Вот процедура, в которой многократно вызывается FindMatches для различных строк и образцов поиска:

public void TestMultiPat

{

//поиск по образцу всех вхождений

string str,strpat,found;

Console.WriteLine("Распознавание языков: чет и нечет");

//четное число нулей и единиц

strpat ="((00|11) * ((01|10) (00|11) * (01|10) (00|11) *)*)";

str = "0110111101101";

FindMatches(str, strpat);

//четное число нулей и нечетное единиц

tring strodd = strpat + "1" + strpat;

FindMatches(str, strodd);

}//TestMultiPat

Коротко прокомментирую работу этой процедуры. Первые два примера связаны с распознаванием языков L1 и L2 (чет и нечет) — языков с четным числом единиц и нулей в первом случае и нечетным числом единиц во втором. Регулярные выражения, описывающие эти языки, подробно рассматривались. В полном соответствии с теорией, константы задают эти выражения. На вход для распознавания подается строка из нулей и единиц. Для языка L1 метод находит три соответствия. Первое из них задает максимально длинную подстроку, содержащую четное число нулей и единиц, и две пустые подстроки, по определению принадлежащие языку L1. Для языка L2 находится одно соответствие — это сама входная строка. Взгляните на результаты распознавания.

Рис. 15.2. Регулярные выражения. Пример "чет и нечет"

Пример "око и рококо"

Следующий образец в нашем примере позволяет прояснить некоторые особенности работы метода Matches. Сколько раз строка "око" входит в строку "рококо" — один или два? Все зависит от того, как считать. Сточки зрения метода Matches, — один раз, поскольку он разыскивает непересекающиеся вхождения, начиная очередной поиск вхождения подстроки с того места, где закончилось предыдущее вхождение. Еще один пример на эту же тему работает с числовыми строками.

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

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

От Двуглавого Орла к красному знамени. Кн. 1

Краснов Петр Николаевич
Белая Россия
Проза:
русская классическая проза
6.80
рейтинг книги
От Двуглавого Орла к красному знамени. Кн. 1

Печать пожирателя 2

Соломенный Илья
2. Пожиратель
Фантастика:
городское фэнтези
попаданцы
аниме
сказочная фантастика
5.00
рейтинг книги
Печать пожирателя 2

В осаде

Кетлинская Вера Казимировна
Проза:
военная проза
советская классическая проза
5.00
рейтинг книги
В осаде

Аргумент барона Бронина 3

Ковальчук Олег Валентинович
3. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Аргумент барона Бронина 3

Моя (не) на одну ночь. Бесконтрактная любовь

Тоцка Тала
4. Шикарные Аверины
Любовные романы:
современные любовные романы
7.70
рейтинг книги
Моя (не) на одну ночь. Бесконтрактная любовь

Свет Черной Звезды

Звездная Елена
6. Катриона
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Свет Черной Звезды

Первый рейд Гелеарр

Саргарус Александр
Фантастика:
фэнтези
5.00
рейтинг книги
Первый рейд Гелеарр

Вторая невеста Драконьего Лорда. Дилогия

Огненная Любовь
Вторая невеста Драконьего Лорда
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Вторая невеста Драконьего Лорда. Дилогия

Пленники Раздора

Казакова Екатерина
3. Ходящие в ночи
Фантастика:
фэнтези
9.44
рейтинг книги
Пленники Раздора

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

Око василиска

Кас Маркус
2. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Око василиска

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

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