Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 224
Текст из файла (страница 224)
з1).4. 1) Аргументы Ь, я, )г11 и е используются так же, как в функциях риг() фасета птп риг (5Р.4.2.2). Аргумент !лг! указывает„используется ли стандартный международный четырехсимвольный знак валюты, или же с этой целью используется какой-нибудь «местный» символ (5Р.4.3.1).
Исходя из топор риг, мы можем определить операцию вывода для Молву (91).4.3): 1О44 Приложение (). Локализация оюгеатз орегаюг«[озсгеать з, Мопеу т) ( озсгеат:: яепйу аиагсс (я) ) У см. У21,3.8 (1:(!аиагс!) гесигп зс сгу ( соим топеу рис<айаг>з)'= изе ~асес<топеу рис<сйаг> > (я.аес(ос() ) с (с'(т==ясассс соя!<!она й~иЫе> (си) ) л'т можно представить кок 1опа с(оиЫе ( (! ( (. рис (з, сгие, я, я .яИ ( ), т ) .)а(1ес( ( ) ) з . зесзсасе (соз Ьаяе: с Ьас(Ыс) с ) есле ( оясг(паз!гает гс г«пс; (( преобразуем в строковое представление [1( !'.рис (з, и ие, я, я.уШ(), г. Ыг() ) .1а!1есс() ) я. зейиасе (юз Ьазе:: Ьас(Ыс) с сассЬ ( ..
° ) ( баас!(е 1оехсербоп (я) с (( см. Я).4,2.2 ) гесигп яс Если для точного представления денежных сумм не хватает типа 1опя с!оиЫе, я преобразовываю значение в его строковое представление и вывожу зто функцией рис(), принимающей строковый аргумент. 0.4.3.3. Ввод денежных величин Фасет споиеу де!читает денежные суммы в соответствии с форматом, заданным с помощью пюпеурцпс(.
Более точно, топеу лес предоставляет функции лес(), которые извлекают надлежащим образом отформатированное представление символов из буфера потока: гетр!асе<с1азз СЬ, с!асс 1п = (ясгеатЬи!' Вегасог<СЬ» с(аяз яМ:: топеуаес с риЫсс !оса!е::)асес ( риЫ1с: (урез(е!' СЬ сйаг сурес сурес(еу 1п 1сег суре с (урез(е(Ьая!с ясппа<СЬ> яй!па (урез ехрйси топеу де! (я(зе с г = О) с ((читаем (Ые) в г по форматным правилом из я; ошибки -устанавливаем ст 1п пес [1п Ь, 1п е, Ьоо( исс1, юз Ьаяеа я, юз Ьаяе.
"сюясасеа г, 1опа с(оиЫеа г) соил!с 1п лес(1п Ь, 1п е, Ьоо(спс1, юз Ьазеа я, юз Ьазе::(оясасеа г, я!с!па (урез г) сопя!с зсайс сосасе: ."Ы !дс о'обьект идентификации фосета (з(З.2, з1).3, ~О.1 1) рппессес(с -топеу де!(); //виртуальные )Со "-функции (см. З(2.4.1) 0,4. Стандартные фасеты 1045 !пг та!и ( ) ( Мопсу т; ««М!е (с!п»т) сои( «т « "~п"; ) Вывод этой программы может быть принят ею в качестве ввода. Более того, вывод, полученный в результате второго запуска этой программы с вводом, равным выводу первого запуска, должен быть идентичен исходному вводу. Операция ввода для Мопеу может выглядеть следующим образом: Ьггеатз орегагог» (Ь(геатз з, Мопеуз т) ( Ь !сеет:: зепйу Оиаг4 (я ); (!" (ОиагИ) ггу ( !оя Ьаяе:: !аз!иге я!а!в = О; ЬягеатЬи! !(ега(ог<сваг> еоз; яягт8 згг; //см.
82!.3.8 // все хорса«о изе 1асея<топеуяея<сйаг» (з.яея!ос () ) .лег (я, еоя, й ие, я!а!в, зй ) (!(я!а(в==О ) ) таге==юз Ьазе::ео!Ь!я) ( !опят!(=яягяо!(ягг.с яяг(),О,О); //проз(с(о!О см. ~20.4.! «2 (еггпо==ЕКА()/СЕ) зяаяе ) = !оз Ьаяе::!а!!Ыя; е1яе з. яеиааяе (я!осе) г саясь (...
) ( Ьап«!!е техсерйоп (я); //см. Я).4.2.2 ге!ига ю ) Здесь использована функция яег(), которая читает в строковую переменную, поскольку чтение в переменную типа «1оиЬ1е с последующим преобразованием в Говд 1п! может привести к потере точности. Аргументы Ь, е, я, 2111 и г используются так же, как в функциях яег() фасета пигп «е! (93.4.2.3).
Аргумент 1пг1 указывает, используется ли стандартный международный четырехсимвольный знак валюты, или же с этой целью используется какой-нибудь «местный» символ (5Р.4.3.1). Правильно определенная пара фасетов топеу «е! и топеу ри! обеспечит вывод в форме, которая может быть считана обратно без ошибок и потери информации. Например: Приложение (). Локализация 104б 0.4.4. Ввод и вывод двт и времени К сожалению, стандартная библиотека С++ не предоставляет удовлетворительного типа для даты.
Из стандартной библиотеки языка С она получает по наследству низкоуровневые средства работы с датами и интервалами времени. Эти средства языка С являются фундаментом для средств С++, позволяющим работать со временем удобным образом, не зависяшим от системных особенностей.
В следующих разделах показывается, как представление дат и времени дня можно сделать чувствительными к контексту локализации. Приводится пример того, как пользовательский тип Ри!е может быть вписан в архитектуру потоков (глава 2)) и контекстов локализации 61з.2). Реализация Оаге демонстрирует технологии, полезные при обрашении со временем в том случае, если у вас нет типа !гаге.
0.4.4.1. Часы и таймеры На самом низком уровне большинство систем имеет таймер, отсчитывающий малые интервалы времени. Стандартная библиотека предоставляет функцию с!осй(), которая возвращает значение зависяшего от реализации арифметического типа с1осй 1. Возврат функции с1осй() может быть откалиброван макросом СЕОСКБ РЕК БЕС. Если у вас нет доступа к надежной утилите измерения времени, можно написать свою собственную измерительную программу: !п! та!п (тг аглс, сваг агин [) ) ( гпг и = аго((аглг(1] ); с!осй ! 11 = с!осй (); )) зб.!.7 )) з20.4.1 )7 с1осй ((-1) означает, что с!осйр не работает гу (г! == с!осй г (-1) ) ( сеп « "зону, по с!осй~п" ! ехй (1); 2ог(!и! г' = О! !<п! !ь'-) Ио зотегй!пл(); с1осй г 12 = с!осй() (!'(12 == с1осй ! (-1 ) ) ( сегг « "зоггу, с1осй очегЯоп' и" ! ех1! (2); ) )) измерительный цика сои! « "Йо лоте!в!пл() "«и«" итез гоой " « г!оиб!е (12 — К) )СЕОСКБ РЕК БЕС « " зесошЬ" « " (теазигетеп! Ксали(агйу: " « СЕОСКБ РЕК БЕС « " о!а зесоп4) '~п"; ) Явное преобразование КоиЫе (12-11) перед операцией деления необходимо, поскольку значение с1осй !может быть целым.
Точное значение, когда начинает работать функция с1осй(), зависит от реализации; предполагается, что с!осй() измеряет интервалы времени в течение одного запуска программы. Для величин 11 и 12, возвращаемых функцией с1осй(), выражение г1оиб!е(12-11) )СЕОСКБ РЕК БЕС является наилучшей оценкой в секундах для времени между двумя вызовами. 0.4. Стандартные фасеты 1047 Если для конкретного процессора таймер не реализован, или если интервал времени слишком велик для измерения, то с(ос!с() возврашает значение с(ос!с г(-1) . Функция с(ос!с() предназначена для измерения интервалов времени длительное)ью от долей секунды до нескольких секунд.
Например, если тип с(осй !есть 32-битовый знаковый 1п! и С(.ОСКБ РЕЯ БЕС равно 1000000, то можно использовать с!хзси () для измерения в микросекундах интервалов от 0 до 2000 секунд (порядка получаса). Обратите внимание, что получение доверительных результатов измерения времени работы программы может оказаться нетривиальным делом. Другие исполняемые на машине программы могут влиять на это время; кэш и взаимодействие между процессами являются труднопрогнозируемыми, да и алгоритмы обработки могут зависеть от данных неожиданным образом.
Если вы уж пытаетесь замерить что-либо, то хотя бы делайте это несколько раз и отбрасывайте сильно отличающиеся результаты как недостоверные. Для работы с более продолжительными интервалами и календарным временем, стандартная библиотека предоставляет тип пте !для представления момента времени и структуру йп для "препарирования*' этого момента: гуреие(!тр1етеи!ат!ои ые))иех( г!те г; // зависящий от реализации арифметический тип //(54.1.1), чаще всего зто 32-Ь(т целое Отметим, что стандарт гарантирует содержание в йп указанных здесь целочисленных полей. Стандарт не гарантирует, что они расположены именно в указанном порядке, или же что нет других полей.
Типы пте ! и йп вместе со стандартными средствами их использования представлены в <опте> и <йте.й>. К примеру: с)ос!х ! с!вся() 1 йхпе 1 йте (йте 1* рг); р текущее календарное врелхя доид)е йт9)(те(Нте ! (2, йте г 11) т р(2-(1 в секундах йп* !оса!йте (соил! йте г* рг]; //местное время для "рг йп* дтйгпе(соизгйте !*р!) т //СгМТ(6геепнлсй Меап Т!те) для ьрг, или 0 р (официально называется Соогх!!потех! !/пыегза( Тгте, ЬТС) гйпе ! т)а!те(ип* рйи); Сйахв авезттЕ (СОПЗ! 1т* ргт); дпте ( для *роя, или йте г(-!) д представление ьрйп в стиле С-строк Р например, "5ип 5ер !б 01:03:52!973)п" сйаг* сйте(соивтйте гл 1) (гетигп азст(те(1осайипе И) ): ) зсгис! йи ( тгтт зес; !иг йи пии; йп гт Моиг; 1ит йи тдау; !игпи тои; ип йп уеагт 1и! !т ич!ау; 1иг гт удау; ип зт Йдзгг )! У секунда минуты [О,б))т бО и 61 — корректировочные секунды //минута часа (0,59) //час дня (0,23) // день лхесяца (1,31) Р месяц года (О,! 1); О значит /апиагу //год после!900; 0 значит 1900, а 102 значит 2002 // день после Яипдау !О, б); О значит Зипх)ау // день после Лапиагу 1 (0,3б5); О значит /апиагу 1 // часы летнего времени // кол-во "тиков" с момента начала работы программы ю048 Приложение О.
Локализация тг та/п (тг асяс, сваг* агяю [] ) //зб.1.7 ( юппе ю(1 = юпле(0) ю Ио а 1ою(агяс,агяч) ю юйле ю 12 = Июле (О) ю Иои01е И = Июле<те ((2, И) ю солю « "йо а 1ою() юоо/ю" « И « "зесолдз'~п" ю ) Если аргумент-указатель функции Ите() не О, то результирующее время записывается и по этому указателю.
Если календарное время не реализовано (например, на специализированных процессорах), то возвращается значение Ите г(-1) . Можно попытаться определить текущую дату следующим образом; тю юла1л () ( «юле ююю юу(Ите(ьб == ате ю(-1) ) ( сеют « "ВаИИте~л»ю ехй (1); ) //ате ЮР// означает, что ате() не работает «п* 0З = лтИте ( щ); солю «яю->«п топ "1 « '/ ' « О(->«и тИау « '/ ' « 1900+0(->«и уеаг«елИ(ю Будьте осторожны — как 1осаййпе(), так и ВтИте () возвращают указатель «л* на статически размещенный объект, так что последовательные вызовы функции изменяют значение этого объекта.
Так что, либо немедленно используйте возвращаемое значение, либо скопируйте «л в управляемую вами область памяти. Аналогично, азсИте () возвращает указатель на статически размещенный массив символов. Структура гт позволяет представить даты в диапазоне по крайней мере десятков тысяч лет (около [-32000,32000[ для минимального размера типа 1«1). В то же время, «те 1 — это чаще всего 32-битовое 1опВ 1«г, что позволяет типу «те г представлять в секундах диапазон длиною в 68 лет в обе стороны от базового года.