Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 226
Текст из файла (страница 226)
Подобно пит яес, фасет йте яес осуществляет доступ к своему буферу посредством пары итераторов ввода: сетр1асе<с!ат СЬ, с!азз 1л = !зсгеатЬи(' йегасог<СЬ» с!ат Ите дес: риЬПс !оса!е::1асес, риЫ(с Ите Ьазе ( риЫ!с: суреИе(СЬ слог суре; Суредеу"1п аег Суре; екр!сс!с Мте де! (з!ье с г = Р); Иасеогдег Ивсе огиег() сопев (ге!игл Ио Иасе огиег(); ) считаем (Ь,е) в И по форматным правилам из з; ошибки - установка г: 1п еес Ите(сп Ь, 1п е, Ыз Ьазеь з, !оз Ьазе::сов!всеь г, ст* И) соле!! 1п еес Ивсе(1п Ь, 1и е, 1оз Ьазеь з, !оз Ьазе::1озсасеь г, ип* И) солт; 1п еесуеаг(1л Ь, 1п е, юз Ьазеь з, !оз Ьазе::из!всеь г, пп* И) солт; сп еес ыееЬИау(1п Ь, 1п е, !оз Ьазеь з, !оз Ьазе::!отасеь г, ип* И) солт; 1п еес топслпате(1п Ь, 1л е, !оз Ьазеь з, соз Ьазе::!озсасеь.г, ип* И) сопя!; згапс !оса!е::Ы Ы; Уобъект идентификации фасета (ЗВ,З, ЗВ.З, ЗО.З.Ц ргосессеИ: -типе ее!(); Увиртуольные чуо "-функции (см.
Я).4.!) Ыпеать орегасог» (Ысгеать з, Расеь И) ( Ысгеат:: зелсгу еиагИ(з) г У см. З2!.3.8 ((( ) РиагИ) ге!игл т юз Ьазе:: !озсасе гез = Р; стх= (Р); сзтгеатЬис йегагогссааг,сваг Сепия<слог» епИг Функция иес йте() вызывает Ио яес йте(). По умолчанию яес сйпе() читает время так, как оно выводится функцией йте рис::рис() в рамках контекста локализации, используя формат чх (5ьз.4.4). Таким образом, простейший вариант операции ввода для типа Расе выглядит примерно так: 1054 Приложение О.
Локализация ( ивеуасег<птеяег<сааг» (в. еег!ос ( ) ) . лег Фаге (в, епФ, в, гев, ах); (1'(гев==0 ( ) гев==гов Ьаве::ео2Ь(г) Ф = Ваге(х.гт тФау, Вагег:Мои!я (х.гт топч-1),х.гтуеаг+1900) г ейе в. веге!иге (гев) г ) сагсЬ ( .. ° ) ( ЬапФ!е !оехсерпоп (в); У см.
ЗВ.4.2.2 ) гегигп вг ) тг гиагп ( ) ггу ( Риге гоФауг сои! « гоФау «епФ!г Ваге Ф (12, Ваге:: тау, 1998); о' пиигем в формате Жх соиг «Ф «епФ!г Ваге ФФ; ггЫ!е (сгп» гЫ) сои! «ФФ «епФ1; ) сагсЬ (Ваге г: ВаФ Фаге) ( сои! « " ехи: ЬаФ Фаге саиеяг~, п" г У читаем даты в формате зй Имеется и версия йте ~ег с суффиксом Ьупате (913.4, ВО.4.1): гетргаге<с!авв СЬ, с!ат 1п = (вггеатви! Ьегагог<СЬ» с!ат вЫг гите еег Ьупате: риЫ(с гипе яег<СЬ,1п> (/* ... */); (З.4.4.5. Более гибкий класс (га1е Если вы попробуете использовать класс Ваге из ЗР.4.4.2 с вводом/выводом из зР.4.4.3 и 91).4.4.4, то вы обнаружите его ограниченность: 1.
Он работает только с датами, представимыми с помощью типа лте г, что в типичном случае означает диапазон (1970,2038]. 2. Он воспринимает даты только в стандартном формате — каков бы он ни был. 3. Его реакция на ошибки ввода неприемлема. 4. Он поддерживает лишь потоки сйаг (а не произвольных символьных типов). Вызов яег Фаге(в, епФ,в, гев, Ьх) полагается на два неявных приведения типа от типа Ыггеапс первый аргумент в используется для создания ЫггеатЬиг' !гегагог; третий аргумент з конвертируется к типу юз Ьазе (базовый класс для Ыггеат).
Эта операция ввода будет работать корректно для дат из диапазона значений, представимых с помощью пте г. Вот несложный тестировочный фрагмент: 1055 0.4. Стандартные фасеты с!ат Ваге ( рив!1с: влит Мопй (!ал=!,~еЬ, таг, арг, тау, гил,)и1, аид, лер, осг, пов, ггес) г вггисг Вагг Нате ( солги слог* голу! Вагг ггаге(сопл!слог*р): плу(р) () )г Ваге(тг йг, Мопй тт, тгуу, 1пг ггау оГ геееИ = О) Ваге() г УУ поместить пи представление Роге в вг УУ возврат лте г представления Роге во!гг тале гт(тг* г) солт! ите г тале йте г() сопл(в !пг уеаг() соля! (ге!игл уг ) Мопй топй () сопл! (ге!игл т; ) Ыг ггпу ( ) сопл! ( гейгп дг ) У...
рг!гаге: слог гг; Молй т; гпг уг Для простоты я вернулся к представлению (г1, т,у) (5)0.2). Конструктор можно определить следующим образом: Ваге::Ваге(1пг гггг, Молй тт, !лгуу, 1лг ггпу о3' говел) : гг(ггвй, т(тт), у(уу) ( (г"(г(==0 аа т==Мопй (О) аа у==О) гегигпг !у Роге(0,0,0) - "нулевая дата" гу'(тт<!ап ) ( Иес<тт) глгогв Вагг ггаге ("Ьагг толй" ); УУ лереупроигено; см. 3"!0.3.
! (г(гЫ<1! ) 3!«Ы) глгогг Вагг ггаге ("Ьагг ггпу оу'топ!ля ) г (г(ггпу о! гвееь аа ггпу т ггееь(уу, тт, ~и) ! = ггпу о) гвееь) глгогг Вагг ггаге (нЬагг ггпу о) гвеел" ) г ) УУ "нулевая дата" Ваге::Ваге(): г((0), т(0), у(0) () Алгоритм г1ау гп )вее!г О весьма нетривиален и не имеет непосредственного отношения к локализациям, так что я отставил его в сторону. Если он вам потребуется, поищите его в рамках вашей системы. Операции сравнения всегда полезны для типов вроде Ваге: Более интересная и полезная операция ввода должна воспринимать более широкий диапазон дат, распознавать несколько распространенных форматов и надежным образом реагировать на ошибки ввода.
Для этого нужно уйти от использования типа пте в Приложение (). Локализация 1056 Ьоо! орегагог== (сопи Вагеа х, сопя! Вага у) ( ге!игл х уеаг() ==у.уеаг() аа х.толгЬ () ==у.топей () ая «.йау() ==у.йгу() г ) Ьоо! орегагог! = (сот( Вагея х, сопя! Вогез у) ( ге!лги ! (х==у); ) Поскольку мы расстались со стандартными типами аи и Рте г, нам нужны будут операции преобразования к этим типам для обеспечения взаимодействия с программами, ожидающими эти типы: юЫ Роге:: тайе гт (гт* р) сот! ( гтх= (О); *р =хг р->ии уеаг = у-1900г р->ли тйау = й; р->гт топ = т-1; ) Йте (Ваге::тайе Вте г() солт ( ф'(у<1970 ! ( 1038<у) У переупрощено гйгоп Вай йоге ("йоге оиг о~гапйе~ог Вте г" ) г ип х; гиа!ге гт(ах) г ге!игл тййте ( ах) ) с!аяя Ваге гогтаг ( найс сйагутг() г сопя! сааг* сигг; сопя( сааг* сиге епйг д умо«читальный формат ,У текущий формат риЬВс: РагеГогтаг(): сиг фиг), сигг епйфимягг!еп фиг) ) ( ) сопя! сааг* Ьее!п ( ) сопя( ( ге!игл сигг; ) сот! сйаг* епй() сопя! (гегигп сиге епй; ) юЫяег(сот! сааг* р, сот! сааг* 9) (сигюр; сигг епй=йг) юЫ яег(сопя! сйаг* р) (сигюрг сигг елй=сигг+ягг!еп (р); ) ягаг!с оотг сйаг* йеуаи!г утг() (ге!игл утгг ) 0.4.4.6.
Задание формата даты Язык С++ не определяет стандартного формата вывода дат (ах является всего лишь наиболее вероятным претендентом; 90.4.4.3). Однако даже если бы и сушествовал стандартный формат, нам все равно потребовались бы альтернативы. Это можно реализовать, предоставив формат по умолчанию и способ его замены. Например: 0.4 Стандартные фасеты 1057 сопл! айаг Ра1е ~огтас::Ттс() = о%А, ЬВай, ВР' српапример, гпйау, геЬгиогу 5 !999 Расеуогтаэ йоге Стг; Чтобы иметь возможность использовать формат зсгСС!те О (В]3.4.4.3), я воздержался от параметризации класса Васе ~огтас по типу используемых символов.
Таким образом, данное решение допускает только те форматы дат, которые представимы с помощью сйаг(). Кроме того, я воспользовался глобальным объектом форматирования йасе !си!для представления формата Васе по умолчанию. Поскольку значение йоге/тс можно изменять, то мы получаем грубый способ управления форматом Васе, аналогичный применению В1оЬа1() (ВР.2.3). Более общим решением было бы определение фасетов Ваге си и Ваее оис для управления чтением и записью в потоки. Этот подход представлен в ЬР.4.4,7.
Располагая Васе /огтас, можно написать операцию Васе:: орегаюг«() следующим образом: гетр!осе<с!азз СЬ, с!азз Тг> Ьасйе озсгеат<СЬ, Тг>ь орегасог«(Ьасйс ожгеот<СЬ, Тг>а з, еопе1 Васеа й) У запись согласно пользовательскому формату ( сурепате Ьасйс озсгеат<СЬ, Тг>::зепоу Виагй(з) с Усм. 92!.3.8 (!(!Виагй) ге1иги з; ип 11 й.таае ии(ас); иу ( сопса с!терис<СЬ>а С'= изе 2асес<йте рис<СЬ» (з.дес!ос () ) с ~(Т.рис(з,з,з.ДНО, ы, йасе ~тс.Ьед!п (), йасе 2тс.еий() ) .ЗаПей() ) з.зеааасе (юз Ьазес:!аИЬ(1) с ) сассЬ (... ) ( Ьапй!е !оехсераоп (з) с И см. ~Р,4.2.2 гесиги з; ) Я мог бы воспользоваться изе7асе( для проверки того, что фасет Ите рис< СЬ> имеется в контексте локализации потока з.
Однако в данном случае проще выглядит вариант с перехватом исключения, генерируемого из изе Тисе!. Приведем простую тестовую программу, управляющую форматом вывода с помощью йасе Иссг. исс таси() ссу ( пЬИе (сйс» йй аа йй ! = Васе () ) сои! «йй «еий!с У исиоль ем умолчат. йасе !тс йоге утС зег ( " жоо У/ ~4т / оой" ) с и ЬИе (с!и» йй а а йй ! = Васе() ) сои! «йй «епй!с ~у используем 'пьКФотсогойо ) сассЬ(Васе: сВай йпсе е) 1058 Приложение О. Локализация сои! «" Ьае Фазе саияЫ: " « е. пБу « епФ1! ) 0.4.4.7. Фасет ввода даты Как всегда, ввод немного сложнее вывода.
Но поскольку интерфейс доступа к низкоуровнему вводу ограничен функцией яег Фаге() и поскольку операция ввода орегаазг»(), определенная для Ваге в 5О.4.4.4, не имеет прямого доступа к представлению Вазе, мы можем воспользоваться этой операцией без изменений. Вот параметризованная версия операции ввода, соответствуюц(ая операции вывода орегагог« () из ~13.4.4.6: гетр(иге<с!азз СБ, с1азз Тг> !ззгеат<СБ, Тг>з орегазог» (1ззгеат<СБ, Тг>я з, Ра1ея Ф) ( (урепате Ьггеат <СБ, Тг>:: зепзгу еиагФ (з); (У(яиагФ) ( !оз Ьазе:: !омаге гез = 0; пах= (О); !ззгеатаи~' Бегаюг<СБ,тг> епФ( изе)асез<Фте еег<СБ» (з.ее(!ос () ) .лег Фазе (з, епФ, з, гез, зх) ! е (сея==0 ) , 'гез==(оз Ьазе::ео)ь1!) Ф= Ра(е (х. 1т теау, Разе:: МопзБ (х. зт тол+1), х.
зтуеаг-';1900, х. гт нч1ау) е!зе я. ее!я!а!е (гез) г ) сазсБ (... ) ( Бале!е юехсерноп (з); д си. 9Р.4.2.2 ) гегиги ю ) Эта операция ввода для типа Ваге вызывает функцию яе! Фаге() из фасета пте еег 5зз.4.4.4) для потока мзгеат. Поэтому можно обеспечить иную и более гибкую форму ввода, определив новый фасет, производный от яйле яес гетр!аге<с)азз СБ, с1азз 1п = 1ззгеатЬиу Бегагог<СБ» с1ат Разе !п: риЫ1с зи1:: 1!те еез<СБ, 1п> риЫ!с: Разе 1и(изе зг = О): з(Ф::г!те еез<СБ> (г) () ргогесзеФ: 1п Фо еез Фа!е(1п Ь, 1л е, юз Ьазея з, юз Ьазе::ютазея г, ил* зтр) сопя!; рг!га1е: епшп Иуре (поги!ие, ипаиовп, ФауоЯееБ, топая); 1п ее!та!(1п Ь, 1п е, юз Ьазез з, юз Базе::1озза(ез г, (лз* г, )где* гез) сопя!! 0.4. Стандартные фасеты Функция бетяа1() должна прочитать год, месяц и день (месяца), а также, возможно, и день недели, после чего составить из этого «и.