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

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

for (vector<vector<string>*>::iterator p = data.begin;

 p != data.end; ++p) {

 delete *p;

}

Либо можно использовать указатель со счетчиком ссылок, такой как

smart_ptr
из проекта Boost, который станет частью будущего стандарта C++0x. Но реализация этого нетривиальна, так что я рекомендую почитать, что такое
smart_ptr
и как он работает. Для получения дополнительной информации по Boost посетите его домашнюю страницу по адресу www.boost.org.

4.24. Использование регулярных выражений для разделения строки

Проблема

Требуется

разделить строку на лексемы, но необходимо выполнить более сложный поиск, чем показано в рецепте 4.7. Например, могут потребоваться лексемы, разделенные более чем одним символом или имеющие несколько различных форм. Это часто приводит к большому коду и путанице среди пользователей вашего класса или функции.

Решение

Используйте шаблон класса

regex
Boost.
regex
позволяет использовать для строк и текстовых данных регулярные выражения. Пример 4.33 показывает, как использовать
regex
для разделения строк.

Пример 4.33. Использование регулярных выражений Boost

#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++ << '\n';

}

Обсуждение

Пример 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), которая является, по всей видимости, наиболее полной и всеобъемлющей из имеющихся библиотек для работы с датами и временем в С++. В некоторых рецептах я буду использовать именно

ее. Сообщество C++ ожидает, что будущие расширения стандартной библиотеки в части работы с датами/временем будут основаны на библиотеке Boost date_time.

Библиотека Boost date_time включает две отдельные системы для работы с датами и временем: одна для работы со временем, и вторая для работы с датами, относящимися к григорианскому календарю. Рецепты описывают обе эти системы.

За дополнительной информацией о датах и времени, в частности об их чтении и записи, обратитесь к главе 13.

5.1. Получение текущей даты и времени

Проблема

Требуется получить от пользователя компьютера текущую дату и время — либо в формате локального времени, либо в формате универсального глобального времени (Coordinated Universal Time (UTC).

Григорианский календарь и високосные годы

Григорианский календарь — это наиболее широко используемый сегодня в западном мире календарь. Григорианской календарь создавался с целью исправить ошибку в юлианском календаре. Медленный процесс адаптации григорианского календаря начался в 1582 году.

Юлианский календарь говорит, что каждый четвертый год — это високосный год, но каждый сотый год — не високосный. Григорианской календарь ввел еще одно исключение — каждый 400-й год должен быть високосным.

Високосные годы предназначены для компенсации несинхронности вращения Земли вокруг Солнца и продолжительности дня. Другими словами, частное отделения продолжительности солнечного года на длительность дня — это не целое число. В результате если календарь не корректировать, то мы получим смещение сезонов, когда равноденствия и солнцестояния (которые определяют сезоны) будут все более и более рассинхронизированы с каждым новым годом.

Решение

Вызовите функцию

time
из заголовочного файла
<ctime>
, передав в качестве параметра значение 0. Результатом будет значение типа
time_t
. Для преобразования значения
time_t
в структуру
tm
, представляющую текущее время UTC (также известное как Greenwich Mean Time (время по Гринвичу), или GMT), используется функция
gmtime
, а для преобразования значения
time_t
в структуру
tm
, представляющую локальное время, используется функция
localtime
. Программа в примере 5.1 получает текущие дату/время, а затем преобразует их в локальное время и выводит на экран. Затем программа преобразует текущие дату/время во время/дату UTC и также выводит результат на экран.

Пример 5.1. Получение локального времени и времени UTC

#include <iostream>

#include <ctime>

#include <cstdlib>

using namespace std;

int main {

 // Текущие дата/время используемой системы

 time_t now = time(0);

 // Преобразуем в структуру tm для локальной временной зоны

 tm* localtm = localtime(&now);

 cout << "Локальные дата и время. " << asctime(localtm) << endl;

 // Преобразуем в структуру tm для UTC

 tm* gmtm = gmtime(&now);

 if (gmtm ! = NULL) {

cout << "Дата и время UTC: " << asctime(gmtm) << endl;

 } else {

cerr << "Невозможно получить дату и время UTC" << endl;

Поделиться с друзьями: