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

где символ w означает любую букву, а символ d — любую цифру. Мы используем символ w (от слова “word”), поскольку символ l (от слова “letter”) слишком легко перепутать с цифрой 1. Эти обозначения вполне подходят для нашего простого примера, но что произойдет, если мы попробуем применить их для описания формата почтового кода, состоящего из девяти цифр (например, TX77845–5629). Что вы скажете о таком решении?

wwddddd–dddd

  Они выглядят вполне логичными, но как понять, что символ d означает “любая цифра”, а знак означает “всего лишь” дефис? Нам необходимо как-то указать, что символы w и d являются специальными: они представляют классы символов, а не самих себя (символ w означает “a или b или c или ...”, а символ d означает “1 или 2, или 3, или ...”). Все это слишком сложно. Добавим к букве, обозначающей имя класса символов, обратную косую черту, как это сделано в языке С++ (например, символ \n означает переход на новую строку). В этом случае получим такую строку:

\w\w\d\d\d\d\d–\d\d\d\d

Выглядит довольно некрасиво, но, по крайней мере, мы устранили неоднозначность, а обратные косые черты ясно обозначают то, что за ними следует “нечто необычное”. Здесь повторяющиеся символы просто перечислены один за другим. Это не только утомительно, но и провоцирует ошибки. Вы можете быстро сосчитать, что перед обратной косой чертой до дефиса действительно стоят пять цифр, а после — четыре? Мы смогли, но просто сказать 5 и 4 мало, чтобы в этом убедиться, поэтому придется их пересчитать. После каждого символа можно было бы поставить счетчик, указывающий количество его повторений.

\w2\d5–\d4

Однако на самом деле нам нужна какая-то синтаксическая конструкция, чтобы показать, что числа 2, 5 и 4 в этом шаблоне являются значениями счетчиков, не просто цифрами 2, 5 и 4. Выделим значения счетчиков фигурными скобками.

\w{2}\d{5}–\d{4}

Теперь символ { является таким же специальным символом, как и обратная косая черта, \, но этого избежать невозможно, и мы должны просто учитывать этот факт.

Итак, все бы ничего, но мы забыли о двух обстоятельствах: последние четыре цифры в почтовом коде ZIP являются необязательными. Иногда допустимыми являются оба варианта: TX77845 и TX77845–5629. Этот факт можно выразить двумя основными способами:

\w{2}\d{5} или \w{2}\d{5}–\d{4}

и

\w{2}\d{5} и необязательно –\d{4}

  Точнее говоря, сначала мы должны выразить идею группирования (или частичного шаблона), чтобы говорить о том, что строки \w{2}\d{5} и –\d{4} являются частями строки \w{2}\d{5}–\d{4}. Обычно группирование выражается с помощью круглых скобок.

(\w{2}\d{5})(–\d{4})

Теперь мы должны разбить шаблон на два частичных шаблона (sub-patterns), т.е. указать, что именно мы хотим с ними делать. Как обычно, введение новой возможности достигается за счет использования нового специального символа: теперь символ ( является специальным, как и символы \ и {. Обычно символ | используется для обозначения операции “или” (альтернативы), а символ ? — для обозначения чего-то условного (необязательного). Итак, можем написать следующее:

(\w{2}\d{5})|(\w{2}\d{5}–\d{4})

и

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

Как и фигурные скобки при обозначении счетчиков (например, \w{2}), знак вопроса (?) используется как суффикс. Например, (–\d{4})? означает “необязательно –\d{4}”; т.е. мы интерпретируем четыре цифры, перед которыми стоит дефис, как суффикс. На самом деле мы не используем круглые скобки для выделения пятизначного почтового кода ZIP (\w{2}\d{5}) для выполнения какой-либо операции, поэтому их можно удалить.

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

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

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

Запись “?” выглядит довольно странно, но знак вопроса после пробела указывает на то, что пробел является необязательным. Если бы мы хотели, чтобы пробел не выглядел опечаткой, то должны были бы заключить его в скобки.

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

Если бы кто-то сказал, что эта запись выглядит слишком неразборчивой, то нам пришлось бы придумать обозначение для пробела, например \s (s — от слова “space”). В этом случае запись выглядела бы так:

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

А что если кто-то поставит два пробела после букв? В соответствии с определенным выше шаблоном это означало бы, что мы принимаем коды TX77845 и TX 77845, но не TX 77845. Это неправильно.

Нам нужно средство, чтобы сказать “ни одного, один или несколько пробелов”, поэтому мы вводим суффикс *.

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

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже