int main(int argc, char** argv) {
if (argc < 2)
return(EXIT_FAILURE);
ifstream in(argv[1]);
if (!in)
return(EXIT_FAILURE);
vector<vector<string>*> data;
loadCSV(in, data);
// Выполнить с данными какие-либо действия...
for (vector<vector<string>*>::iterator p = data.begin();
p != data end(); ++p) {
delete *p; // Убедитесь, что p
} // разыменован!
}
В примере 4.32 почти нет ничего, что еще не было бы описано, getline
обсуждается в рецепте 4.19, a vector
— в рецепте 4.3. Единственный фрагмент, заслуживающий упоминания, — это выделение памяти.
loadCSV
создает новый vector
для каждой прочитанной строки данных и сохраняет его в другом vector, состоящем из указателей на vector
. Так как память для каждого из этих векторов выделяется из кучи, кто-то должен удалить ее, и этот кто-то — это вы (а не реализация vector
).
vector
ничего не знает о том, содержит ли он значение или указатель на значение или что-либо еще. Все, что он знает, — это то, что при его удалении он должен вызвать деструктор для каждого содержащегося в нем элемента. Если vector
хранит объекты, то все нормально, объект будет удален правильно. Но если vector
содержит указатели, то удалены будут указатели, а не объекты, на которые они указывают.
Есть два способа гарантировать освобождение памяти. Первый заключается в том, что сделано в примере 4.32 вручную, как здесь.
for (vector<vector<string>*>::iterator p = data.begin();
p != data.end(); ++p) {
delete *p;
}
Либо можно использовать указатель со счетчиком ссылок, такой как smart_ptr
из проекта Boost, который станет частью будущего стандарта C++0x. Но реализация этого нетривиальна, так что я рекомендую почитать, что такое smart_ptr
и как он работает. Для получения дополнительной информации по Boost посетите его домашнюю страницу по адресу
4.24. Использование регулярных выражений для разделения строки
Требуется разделить строку на лексемы, но необходимо выполнить более сложный поиск, чем показано в рецепте 4.7. Например, могут потребоваться лексемы, разделенные более чем одним символом или имеющие несколько различных форм. Это часто приводит к большому коду и путанице среди пользователей вашего класса или функции.
Используйте шаблон класса regex
Boost. regex
позволяет использовать для строк и текстовых данных регулярные выражения. Пример 4.33 показывает, как использовать regex
для разделения строк.
#include <iostream>
#include <string>
#include <boost/regex.hpp>
int main() {
std::string s = 'who,lives-in-a,pineapple under the sea?';
boost::regex re(',|:|-|\s+'); // Создаем регулярное выражение
boost::sregex_token_iterator // Создаем итератор, используя
p(s.begin(), s.end(), re, -1), // последовательность и это выражение
boost::sregex_token_iterator end; // Создаем маркер
// «конец-рег-выражения»
while (p != end)
std::cout << *p++ << '
';
}
Пример 4.33 показывает, как использовать regex
для перебора соответствий регулярному выражению. Следующая строка создает регулярное выражение.
boost::regex re(' ,|:| -|\s+');
Она гласит, что каждое соответствие регулярному выражению — это либо запятая, либо двоеточие, либо тире, либо один или несколько пробелов. Символ канала — это логический оператор OR, используемый для объединения разделителей. Следующие две строки создают итератор.
boost::sregex_token_iterator
p(s.begin(), s.end(), re, -1);
boost::sregex_token_iterator end;
Итератор p
создается с помощью регулярного выражения и входной строки. После его создания p
можно рассматривать как итератор для последовательности из стандартной библиотеки, sregex_token_iterator
создается без аргументов и является специальным значением, представляющим конец последовательности лексем регулярного выражения, и, следовательно, может использоваться для проверки достижения конца.
Глава 5
Даты и время
5.0. Введение
Даты и время являются удивительно обширным и сложным вопросом. Как отражение этого факта, стандартная библиотека C++ не предоставляет подходящего типа данных для дат. C++ наследует структуры и функции для работы с датами и временем, а также пару функций ввода и вывода дат/времени с учетом локализации, от С. Однако решение можно найти в библиотеке date_time Library из состава Boost, написанной Джеффом Гарландом (Jeff Garland), которая является, по всей видимости, наиболее полной и