Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 224
Текст из файла (страница 224)
Г.4.4.1. Часы и таймеры На самом низком уровне большинства систем имеется таймер, отсчитывающий очень маленькие интервалы времени. Стандартная библиотека предоставляет функцию с1осй(), которая возвращает значение зависящего от реализации типа с1ос/е 1. Результат, возвращаемый с1ос/е(), можно откалибровать с помощью макроса СЕОСКЯ РЕК ЯЕС. Прн отсутствии надежной утилиты измерения времени, нетрудно написать собственный измерительный цикл наподобие следующего: !п1таш(!п1агус, с/лаг" аг!1о[)) // у 6.!.7 ( т1п = а!о!(асуп[1)); //у 20нй! ' с!ос)л ! !1 = с!оси(); !/(1!==с!ос/л 1(-1)) ( //с!оол !( — Ц означати "с!ос!<О не работает" сегг « "извините, нет часов лп', ехд(1), /ог(!и!1=0; !<п; !++) до зете!/л!пу(1 //измерительный авил с!осй 1 12 = с!ос/л(); !/(12==с!ос/с !(-1)) ( сегг « 'извините, часы зашкалало уп, ехн(2); сои1 « "выполнение с!о зете!/л!пуО "«п « "раз заняло" «ноиб!е(12-!!)/СЕОСКЯ РЕй ЯЕС «секунд" « ' (частота таймера:" «СЕОСКЯ РЕ11 ЯЕС «" в секунду)~п"; Явное преобразование с(оиЫе(12-11) перед операпией деления необходимо, потому что значение с1осй !может быть целым.
Точное значение, с которого начинается работа с1ос/е(), зависит от реализации; назначением с1ос/е() является измерение интерва- Приложение Г Локализация 986 Еурег/е/ Етр!етепга!Еоп г/е/!пег! Ите Е; // зависяиЕий опг реализации // арггфлге>иггческгггг пшп Ц 4.!. !) // спосодньш хранить период времени //зачастую — 32-битное целое зпхгс! Ет ( 1п10п зес, // секунда минуты /06! /; 60 а Г> ! зарезервированы // для корреклгировочных секунд //лгинута часа /0,59/ // час суток /0,23/ 0 день лгесяца / 1,3 ! / //лгетц года /О, ! ! /; О означает январь /вюгматгег не /1, ! 2/) // год от ! 900; 0 означает ! 900 год, а ! 02 — 2002 еод // день недели /О,б/; О означает воскресенье // день года /0,365/; О означает ! января // часы летнего времени т1 Епг тт; тЕЕт /гонг т11т тг/ау, т11т топ; !п1 Ет уеа>;.
!п1 Ет тс/ау; гп10п удау; т1Ет !здзЕ; Стандарт гарантирует только то, что в 1т имеются перечисленные выше целые члены. Стандарт не гарантирует, что они расположены именно в таком порядке, или что отсутствуют другие поля. Типы 1!те 1 и Ет вместе с базовыми средствами их использования объявлены в <с11теь и с!!те./гь, Примеры: с!ос!ч 1с!ос/г(); // кояичеопво 'тиков" с лголгента заг>уска // програлшы Пте 11!те(1!те 1. 'р!); долгу!егЕ>ЯНте(1!те Е Е2, Пте 111), // текугцее календарное время // 12 — и в секундах Ет* !оса/!!те(сопз1 1>те 1' рЕ! // местное врелгя дяя "р! лов времени в течение одного запуска программы.
Если имеются 11 и !2, полученные в результате вызовов с1ос/г(), г/оиЫе(12-11) / СЕОСК РЕ/Е ВЕС является наилучшей возможной оценкой времени в секундах между двумя вызовами. Если у данного процессора отсутствует таймер, или интервал времени слишком велик для измерения, с1ос/г() возвращает значение с1осй Е(-1). Функция с1ос/г() предназначена для измерения интервалов длительностью от доли секунды до некоторого количества секунд. Например, если с1ос/е !означает 32- битный Еп/ со знаком и СЕОСКЬ РЕК БЕС равно 1000000, мы можем пользоваться с1ос/г() для измерения интервалов от 0 до 2000 секунд (порядка по.лучаса) в микросекундах.
Заметим, что получение разумных результатов измерения времени выполнения программы может оказаться непростым делом. Другие выполняемые на машине программы могут оказывать значительное влияние на время исполнения; время на кэширование н межзадачный обмен трудно предугадать, да и алгоритмы обработки могут зависеть от данных самым неожиданным образом. Пытаясь засечь время, сделайте несколько замеров и отбросьтс результаты как недействительные, если они значительно варьируются от запуска к запуску. Чтобы управиться с более продолжительными интервалами и с календарным временем, стандартная библиотека предоставляет тип !Ете !для указания момента времени и структуру 1т для его разлелення на составные части: 987 Г4. Стандартные фасеты 1т*ят11те(сопя/нте Г«р1); О Время по!ринвину (Б/ЛТ), соответтпвувиЛее // *р! или 0 // (офиииально назьтаегпся сноординированнилс универсальннл~ временели 1!ТС) О 1ипе ! для «р1т шли Оте 1( — !) Ите 1тнг!те(1т" р1т) сдпг«августе(сопв11т' р1т); О представление времени "р1т в виде С-с«прони, // например 'Вип Вер 16 0! «03:52 1973',и" с!ьаг' сите(сопя! 1ипе 1* 1) ( ге!ига авс11те(!оса!1!те(1)'; ) гп1та!п(1п1агус, с)«аг«агТсв()) ( // 5 5.!.7 Нте 1Ы =гине(0), г!о а 1ойа«Ос, агав); Оте 112 = Тйпе(0); с!оид!е «1 = с!Озг!те(12, 1!), сои1« "выполнение«!о а !о1() заняло" «д«'секунд«п', Если аргумент-указатель 1!те() не равен О, текущее время также записывается по ад- ресу указателя на 1!те 1.
Если календарное время недоступно (например, в специа- лизированном процессоре), возвращается значение !!те 1(-!), Можно попытаться осторожно определить ссгодняшнюю дату следующим образом: сп1 тат() ( Будьте осторожны: как 1оса11!те(), так и От1!те() возвращают указатель 1т' на статически размещенный объект, так что последующие вызовы функпии изменят значение объекта. Либо используйте возвращаемое значение немедленно, либо скопируйте 1т в управляемую вами область памяти, Аналогично, авс1!те() возвращает указатель на статически размещенный массив символов.
Структура 1т может представлять даты в диапазоне по меньшей мере десятков тысяч лет (примерно (-32000, 32000) в случае минимального размера сл1). С другой стороны, 1!те 1, как правило, является 32-битным целым (со знаком). Это позволяет 1!те !представлять в секундах диапазон длинною чуть более б8 лет в обе стороны от базового года. Этим базовым гадом обычно является 1970, точным базовым временем при этом является 0:00, 1 января по Гринвичу, Прн 32-битпом целом (со знаком) 1!те 1, в 2038 году мы окажемся «вне времени», если не изменим 1!те 1 на больший целый тип, что уже сделано на некоторых системах. Механизм 1!те !задуман в первую очередь для представления «близкого к настоящему времени».
Таким образом, мы не вправе ожидать, что 1!те !сумеет хранить даты вне пределов диапазона (1902, 2038). Что еще хуже, не все реализации функций времени одинаково воспринимают отрицательное время. Из соображений переносимостзл значение, которое должно быть представимо и как 1т, и как 1!те 1, обязано лежать в диапазоне [1902, 20381. «1тобы представить !1аты впе этого диапазона, придется придумать некий дополнительный механизм. Одно из последствий вышесказанного — возможный сбой т/е1!те().
Если аргумент т/с1!те() не может быть представлен как 1!те 1, буде.г возвращен индикатор ошибки 1!те 1(-1). Хронометраж в «долгоиграющей» программе можно реализовать так: Приложение Г Локализация 988 Вте 11 1/(1!те(йгг==1!те 1(-!((( //Вте Ц-!) означаеои что "1гтеО // не радогпаегп сегг « 'Влохое время.. ~,п; ехВ(1] 1 1т' у! = дтнте(йб; сои! «91->1т топ +1 «'/'«91 — 1т тйау«'/' «!900ч91 — >1т уеаг«епй!, Г.4.4.2. Класс Эа1е с1аяя,Раяе ( риЫ(с епит Мопяпг/ап=1 /еЬ, таг, арг, тау, !ип, 1и1, аид, зер, ос1, поо, йес1; с!аяз Вай йоге (1, // исключение Ра1е(ш1 йй, МопЯ тт, Я1уу(; Раяе((; /пепй ок1геатй орега1ог«(ок1геатй я, сопя1 Рагей й(; // -..
рггоа1е: 1ипе 1й: // стандартное представление даты и времени Ра1есРа1е(!п1 йй, Моп1Ь тт, !п1 уу( ( 1т х = ( 0 1; г/(йй<О((9!<йй(йгогоВай йаяе((. х.1т тйау= йй, гЛтт<!ап (( йес<тпг( Ягою Вай йа1е(( хят топ= тт — !; х 1т уеаг = уу — 1900; г1 = тЫгте(йх(; //чрезмерно упрощенно: см 9 10.3,! //1т топотсчитываютснуля /,г 1т уеаготс штывзюгп с 1900 Риге:граге() ( й = 1!те(О(, // значение по умолчанию для Расе (сегодня) гя(й== Ите У;!(( 1ЬгоюВай йа1е((, Перед нами стоит задача реализовать зависящие от локализации операторы «и» для Ра1е. Как отмечалось в 9 10.3, маловероятно, чтобы единственный тип Ра1е смог удовлетворить все потребности. Различные цели использования информации о дате диктуют наличие множества представлений, а календарные сведения до 19-го столетия сильно зависят от капризов истории. Тем не менее, в качестве примера мы можем определить тип Ра1е примерно как в 9 10.3, реализуя его через 11гпе 1: Г 4. Стандартные фасеты 989 Г.4.4.3.
Вывод даты и времени Также как и питри1 (6 Г.4.2), 1(терц! предоставляет ри1[)-функции для записи в буферы через итераторы: 1етр!а1ечс!аяя СЬ, с!аял Ои1 = оя1геаплби/ !1ега1огчСЬ» с!аяя я1бчите ри1: риЬ!!с !оса!е;/асег ( риЬ!!с. 1урег!е/СЬ сЬаг 1уре; Гурел!е/Ои1 нег 1уре, схрйсннте риг(я!хе 1г= О); // поллестить !в буфер поплока я через Ь, используя форлчолп/лп1; Ои1 ри1(ОигЬ, !оя болей я, СЬЯ!1, сопяггт* 1, сопя1 СЬ'/т1 Ь, сопя! СЬ'/т1 е) сопя!, Оиг ри1(Ои1 Ь, лоя ЬаяеЬ я, СЬ/л!1, сопя! гт" 1, сЬаг/т1 сдпг тос! = О) сопя! (ге1игп Ыо ри1(Ь, я,/!!1, 1,/тг, тог!); ) ягаис!оса!ес!л!!лг; //идентификатор фасста (З Д4, З" ДО, З" ДЗ.!) рго1ес1ес1: -Нтс риг(); о!ггиа! Оиг Ыо риООиг, !оя Ьаяесч СЬ, сопя11т", сЬаг, сдпг) сопя!; ); Вызов ри1(Ь, я,рл!(, 1, /т! Ь, /т1 е) помещает информацию о дате из !в буфер потока я через Ь. Прц необходимости в качестве заполнителя используется символ Я!!.
Форлиат вывода задается чрг!л(г])-подобной» строкой форматирования [/т! Ь, /т! е), Этот рг!пЯ-подобный формат (9 21.8) производит выходную строку н может содержать следующие специа.льные спецификаторы формата; %а сокращенное название дпя недели (например, 5аг) ' А полное название дня недели (напрпмер, 5анггс(ау) ' Ь сокращенное название месяца (например, геЪ) %В полное название месяца (например, геЪгпагу) %с дата и время (например, Ваг ГеЪ 06 21;46;05 1999) %л! число [01, 31] (например, 06) '/ьН 24-часовой формат времени [00,23] (например, 2!) %У 12-часовой формат времени [01,12] (например, 09) ьУ! день года [001, 366] (например, 037) чвт месяц [01, 12] (например, 02) %М минута часа [00, 59] (например, 48) ь р а.пь/рзп.
(до/после полудня), индикатор для 12-часового формата (например, РМ) %8 секунда в минуте [ОО, 61] (например, 40) %(/ неделя года [00, 53] начиная с воскресенья (например, 05); первое воскресенье начинает первую неделю %в день недели [О, 6]; 0 означает воскресенье (например, 6); %)г' неделя года [00, 53] начиная с понедельника (например, 05); первый понедельник ьлачпнает первую неделю %х дата (например, 02/06/99) 990 Приложение Г Локализация %Х время (например, 21;48;40) %у год без века (00, 99) (например, 99) %У год (например, 1999) %Х индикатор часового пояса (например, Е8Т) если часовой пояс известен Столь длинный список весьма специальных правил форматирования может послужить аргументом в пользу выбора какой-либо расширяемой системы ввода/вывода.