Потоки ввода-вывода и класс string
string s;
while (cin>>s) {
if (s.size==7
&& isalpha(s[0]) && isalpha(s[1])
&& isdigit(s[2]) && isdigit(s[3]) && isdigit(s[4])
&& isdigit(s[5]) && isdigit(s[6]))
cout << " найдена " << s << '\n';
}
Здесь значение isalpha(x)
true
, если x
— это буква, а значение isdigit(x)
равно true
, если x
— цифра (см. раздел 11.6). В этом (слишком) простом решении кроется несколько проблем.• Оно громоздко (четыре строки, восемь вызовов функций).
• Мы пропускаем (умышленно?) почтовые индексы, не отделенные от своего контекста пробелом (например, "TX77845
", TX77845–1234 и ATX77845).• Мы пропускаем (умышленно?) почтовые индексы с пробелом между буквами и цифрами (например, TX 77845
).• Мы принимаем (умышленно?) почтовые индексы, в которых буквы набраны в нижнем регистре (например, tx77845
).• Если вы решите проанализировать почтовые индексы, имеющие другой формат (например, CB3 0FD
), то будете вынуждены полностью переписать весь код.Должен быть более хороший способ! Перед тем как его описать, рассмотрим поставленные задачи. Предположим, что мы хотим сохранить “старый добрый код”, дополнив его обработкой указанных ситуаций.
• Если мы хотим обрабатывать не один формат, то следует добавить инструкцию if
switch
.• Если мы хотим учитывать верхний и нижний регистры, то должны явно конвертировать строки (обычно в нижний регистр) или добавить дополнительную инструкцию if
• Мы должны как-то (как?) описать контекст, в котором выполняется поиск. Это значит, что мы должны работать с отдельными символами, а не со строками, т.е. потерять многие преимущества, предоставляемые потоками iostream
Если хотите, попробуйте написать код в этом стиле, но нам очевидно, что в этом случае вы запутаетесь в сети инструкций if
123!
и 123456!
). В конце концов, нельзя забывать о префиксах и суффиксах. Как мы уже указывали (см. разделы 11.1 и 11.2), предпочтения пользователей по отношению к разным форматам не ограничиваются стремлением программистов к систематичности и простоте. Просто подумайте о разнообразных способах записи одной только даты.2007–06–05
June 5, 2007
jun 5, 2007
5 June 2007
6/5/2007
5/6/07
...
В этот момент, если не раньше, опытный программист воскликнет: “Должен быть более хороший способ!” (чем нагромождение ординарного кода) и станет его искать. Простейшим и наиболее широко распространенным решением этой задачи является использование так называемых
Регулярные выражения являются основой большинства методов обработки текстов и команды grep
Регулярные выражения, которые мы будем использовать, реализованы в библиотеке, которая станет частью следующего стандарта языка С++ (C++0x). Они сопоставимы с регулярными выражениями из языка Perl. Этой теме посвящено много книг, учебников и справочников, например, рабочий отчет комитета по стандартизации языка C++ (в сети веб он известен под названием WG21), документация Джона Мэддокса (John Maddock) boost::regex
ПОПРОБУЙТЕ
В последних двух абзацах “неосторожно” упомянуты несколько имен и аббревиатур без каких-либо объяснений. Поищите в веб информацию о них.
23.6. Идея регулярных выражений
Основная идея регулярного выражения заключается в том, что оно определяет
wwddddd