if (!boost::regex_match(line, matches, header)) {
error("Нет заголовка");
}
}
// суммы по столбцам:
int boys = 0;
int girls = 0;
while (getline(in,line)) {
++lineno;
smatch matches;
if (!regex_match(line, matches, row))
cerr << "Неправильная строка: " << lineno << '\n';
if (in.eof()) cout << "Конец файла\n";
// проверяем строку:
int curr_boy = from_string
int curr_girl = from_string
int curr_total = from_string
if (curr_boy+curr_girl != curr_total)
error("Неправильная сумма\n");
if (matches[1]=="Alle klasser") { // последняя строка
if (curr_boy != boys)
error("Количество мальчиков не сходится\n");
if (curr_girl != girls)
error("Количество девочек не сходится\n");
if (!(in>>ws).eof())
error("Символы после итоговой строки");
return 0;
}
// обновляем суммы:
boys += curr_boy;
girls += curr_girl;
}
error("Итоговой строки нет");
}
Последняя строка по смыслу отличается от остальных: в ней содержатся суммы. Мы распознаем ее по метке (“Alle klasser”). Мы решили, что после последнего символа не должны стоять символы, не являющиеся разделителями (для распознавания этого факта используется функция lexical_cast()
(см. раздел 23.2)), и выдаем сообщение об ошибке в случае их обнаружения.
Для того чтобы извлечь числа из полей данных, мы использовали функцию from_string()
из раздела 23.2. Мы уже проверили, что эти поля содержат только цифры, поэтому проверять правильность преобразования объекта класса string
в переменную типа int
не обязательно.
Регулярные выражения — популярный и полезный инструмент, доступный во многих языках программирования и во многих форматах. Они поддерживаются элегантной теорией, основанной на формальных языках, и эффективной технологией реализации, основанной на конечных автоматах. Описание регулярных выражений, их теории, реализации и использования конечных автоматов выходит за рамки рассмотрения настоящей книги. Однако поскольку эта тема в компьютерных науках является довольно стандартной, а регулярные выражения настолько популярны, найти больше информации при необходимости не составляет труда.
Перечислим некоторые из этих источников.
Aho, Alfred V., Monica S. Lam, Ravi Sethi, and Jeffrey D. Ullman. Compilers: Principles, Techniques, and Tools, Second Edition (обычно называемая “The Dragon Book”). Addison-Wesley, 2007. ISBN 0321547985.
Austern, Matt, ed. “Draft Technical Report on C++ Library Extensions”. ISO/IEC DTR 19768, 2005. www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n2336.pdf.
Boost.org. Хранилище библиотек, согласованных со стандартной библиотекой языка С++. www.boost.org.
Cox, Russ. “Regular Expression Matching Can Be Simple and Fast (but Is Slow in Java, Perl, PHP, Python, Ruby, ...)”. http://swtch.com/~rsc/regexp/regexp1.html.
Maddoc, J. boost::regex documentation. www.boost.org/libs/regex/doc/index.html.
Schwartz, Randal L., Tom Phoenix, and Brian D. Foy. Learning Perl, Fourth Edition.
O’Reilly, 2005. ISBN 0596101058.
Задание
1. Выясните, является ли библиотека regex
частью вашей стандартной библиотеки. Подсказка: ищите std::regex
и tr1::regex
.
2. Запустите небольшую программу из раздела 23.7; для этого может понадобиться инсталлировать библиотеку boost::regex
на вашем компьютере (если вы этого еще не сделали) и настроить опции проекта или командной строки для установления связи с библиотекой regex
, а затем использовать заголовки regex
.
3. Используйте программу из задания 2 для проверки шаблонов из раздела 23.7.
Контрольные вопросы
1. Где мы находим “text”?
2. Какие возможности стандартной библиотеки чаще всего используются для анализа текста?
3. Куда вставляет элемент функция insert()
— перед или после указанной позиции (или итератора)?
4. Что такое Unicode?
5. Как конвертировать тип в класс string
и наоборот?
6. В чем заключается разница между инструкцией cin>>s
и вызовом функции getline(cin,s)
, если s
— это объект класса string
?
7. Перечислите стандартные потоки.
8. Что собой представляет ключ ассоциативного массива map
? Приведите примеры полезных типов для ключей.
9. Как перемещаться по элементам контейнера класса map
?