⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fac_3537.htm

📁 C++标准库 C++标准库 C++标准库 C++标准库
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD><TITLE>1.5 The Facets</TITLE></HEAD><BODY><A HREF="ug2.htm"><IMG SRC="images/banner.gif"></A><BR><A HREF="loc_1541.htm"><IMG SRC="images/prev.gif"></A><A HREF="booktoc2.htm"><IMG SRC="images/toc.gif"></A><A HREF="use_1194.htm"><IMG SRC="images/next.gif"></A><BR><STRONG>Click on the banner to return to the user guide home page.</STRONG><H2>1.5 The Facets</H2><P>A facet is a nested class inside class <SAMP>locale</SAMP>; it is called <SAMP>locale::facet</SAMP>.  Facet objects encapsulate internationalization services, and represent culture and language dependencies.  </P><A NAME="1.5.1"><H3>1.5.1 Creating a Facet Object</H3></A><P>There are several ways to create facet objects:</P><UL><LI><P>Buy a facet library, which provides you with facet classes and objects.</P></LI><LI><P>Build your own facet classes and construct facet objects.</P></LI><LI><P>Build facet objects from the external representation of a C locale.  This is done via the constructor of one of the byname<A HREF="endnote2.htm#fn9">[9]</A> facet classes from the Standard C++ Library, as shown in Figure 11:</P></LI></UL><H4>Figure 11.  Creating facet objects</H4><BR><IMG SRC="images/image11.gif"><P>Facets are interdependent.  For example, the<SAMP> num_get</SAMP> and <SAMP>num_put</SAMP> facet objects rely on a <SAMP>numpunct</SAMP> facet object.  In most cases, facet objects are not used independently of each other, but grouped together in a locale object.  For this reason, facet objects are usually constructed along with the locale object that maintains them.</P><P>On rare occasions, however, you may need to construct a single facet for stand-alone use.  You will then find that you cannot construct a facet directly, because the <SAMP>facet</SAMP> class has a protected destructor. <A HREF="endnote2.htm#fn10">[10]</A> The example below demonstrates how to write the code to construct and use a single facet object.  This code demonstrates a locale-sensitive string comparison, which you would perform in C using the <SAMP>strcoll()</SAMP> function.</P><PRE>template &#60;class charT>class Collate : public collate_byname&#60;charT>{public:   Collate(const char* name, size_t refs=0)   : collate_byname&#60;charT>(name,refs) {}   ~Collate() {}};string name1("Peter Gartner");string name2 ("Peter G_rtner");Collate&#60;char> collFacet("De_DE");                             \\1if ( collFacet.compare                                        \\2   (name1.begin(), name1.end(), name2.begin(), name2.end())    == -1){ _ }</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>A collation facet object is constructed from a German C locale's external representation.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The member function<SAMP> compare()</SAMP> of this facet object is used for string comparison.</TD></TR></TABLE><P>The string class in the Standard C++ Library does not provide any service for locale-sensitive string comparisons.  Hence, you will generally use a collate facet's compare service, as demonstrated above, or the locale's function call operator instead:</P><PRE>string name1("Peter Gartner");string name2 ("Peter G_rtner");locale loc("De_DE");if ( loc(name1, name2) ){ _ }</PRE></LI></UL><A NAME="1.5.2"><H3>1.5.2 Accessing a Locale's Facets</H3></A><P>A locale object is like a container--or a map, to be more precise--but it is indexed by type at compile time.  The indexing operator, therefore, is not <SAMP>operator[]</SAMP>, but rather the template operator <SAMP>&#60;></SAMP>.  Access to the facet objects of a locale object is via two member function templates, <SAMP>use_facet</SAMP> and <SAMP>has_facet</SAMP>:</P><PRE>template &#60;class Facet> const Facet&#38;     use_facet(const locale&#38;);template &#60;class Facet> bool             has_facet(const locale&#38;);</PRE><P>The code below demonstrates how they are used.  It is an example of the <SAMP>ctype</SAMP> facet's usage; all upper case letters of a string read from the standard input stream are converted to lower case letters and written to the standard output stream.</P><PRE>string in;cin >> in;if (has_facet&#60; ctype&#60;char> >(locale::locale()))               \\1{  cout &#60;&#60; use_facet&#60; ctype&#60;char> >(locale::locale())         \\2               .tolower(in.begin(),in.end());                 \\3}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>In the call to <SAMP>has_facet&#60;...>()</SAMP>, the template argument chooses a facet class.  If no object of the named facet class is present in a locale object, <SAMP>has_facet</SAMP> returns <SAMP>false</SAMP>. </TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The function template <SAMP>use_facet&#60;_>()</SAMP> returns a reference to a locale's facet object.  As locale objects are immutable, the reference to a facet object obtained via <SAMP>use_facet()</SAMP> stays valid throughout the lifetime of the locale object. </TD></TR><TR VALIGN="top"><TD>//3</TD><TD>The facet object's member function <SAMP>tolower()</SAMP> is called.  It has the functionality of the C function <SAMP>tolower()</SAMP>; it converts all upper case letters into lower case letters.</TD></TR></TABLE><P>In most situations, you do not have to check whether a locale has a standard facet object like <SAMP>ctype</SAMP>.  Most locale objects are created by composition, starting with a locale object constructed from a C locale's external representation.  Locale objects created this way, that is, via a byname constructor, always have all of the standard facet objects.  Because you can only add or replace facet objects in a locale object, you cannot compose a locale that misses one of the standard facets.</P><P>A call to <SAMP>has_facet()</SAMP> is useful, however, when you expect that a certain non-standard facet object should be present in a locale object.</P><A NAME="1.5.3"><H3>1.5.3 Using a Stream's Facet</H3></A><P>Here is a more advanced example that uses a time facet for printing a date.  Let us assume we have a date and want to print it this way:</P><PRE>struct tm aDate;                                              //1aDate.tm_year = 1989;aDate.tm_mon = 9;aDate.tm_mday = 1;                                            //2cout.imbue(locale::locale("De_CH"));                          //3cout &#60;&#60; aDate;                                                //4</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>A date object is created.  It is of type <SAMP>tm</SAMP>, which is the time structure defined in the standard C library.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The date object is initialized with a particular date, September 1, 1989.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>Let's assume our program is supposed to run in a German-speaking canton of Switzerland.  Hence, a Swiss locale is attached to the standard output stream.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>The date is printed in German to the standard output stream.</TD></TR></TABLE><P>The output will be: <SAMP>1. September 1989</SAMP></P><P>As there is no <SAMP>operator&#60;&#60;()</SAMP> defined in the Standard C++ Library for the time structure <SAMP>tm</SAMP> from the C library, we have to provide this inserter ourselves.  The following code suggests a way this can be done.  If you are not familiar with iostreams, you will want to refer to the iostreams section of this User's <I>Guide</I> for more information. </P><P>To keep it simple, the handling of exceptions thrown during the formatting is omitted.</P><PRE>template&#60;class charT, class traits>basic_ostream&#60;charT, traits>&#38;operator&#60;&#60;(basic_ostream&#60;charT,traits>&#38; os, const tm&#38; date)   \\1{ locale loc = os.getloc();                                    \\2 typedef ostreambuf_iterator&#60;charT,traits> outIter_t;         \\3 const time_put&#60;charT,outIter_t>&#38; fac;                        \\4 fac = use_facet &#60; time_put&#60;charT, bufIter_t > > (loc);       \\5 outIter_t nxtpos;                                            \\6 nextpos = fac.put(os,os,os.fill(),&#38;date,'x');                \\7 if (nxtpos.failed())                                         \\8    os.setstate(ios_base::badbit);                            \\9 return os;}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>This is a typical signature of a stream inserter; it takes a reference to an output stream and a constant reference to the object to be printed, and returns a reference to the same stream.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The stream's locale object is obtained via the stream's member function <SAMP>getloc()</SAMP>.  This is the locale object where we expect to find a time-formatting facet object.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>We define a type for an output iterator to a stream buffer. <BR><BR>Time formatting facet objects write the formatted output via an iterator into an output container (see the sections on containers and iterators in the <I>User's</I> <I>Guide</I>).  In principle, this can be an arbitrary container that has an output iterator, such as a string or a C++ array. <BR><BR>Here we want the time-formatting facet object to bypass the stream's formatting layer and write directly to the output stream's underlying stream buffer.  Therefore, the output container shall be a stream buffer.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>We define a variable that will hold a reference to the locale object's <SAMP>time_put</SAMP> facet object.  The time formatting facet class <SAMP>time_put</SAMP> has two template parameters:<BR><BR>The first template parameter is the character type used for output.  Here we provide the stream's character type as the template argument.<BR><BR>The second template parameter is the output iterator type.  Here we provide the stream buffer iterator type <SAMP>outIter_t</SAMP> that we had defined as before.</TD></TR><TR VALIGN="top"><TD>//5</TD><TD>Here we get the time-formatting facet object from the stream's locale via <SAMP>use_facet()</SAMP>.</TD></TR><TR VALIGN="top"><TD>//6</TD><TD>We define a variable to hold the output iterator returned by the facet object's formatting service.</TD></TR><TR VALIGN="top"><TD>//7</TD><TD>The facet object's formatting service <SAMP>put()</SAMP>is called.  Let us see what arguments it takes.  Here is the function's interface:</TD></TR></TABLE><PRE>     iter_type put     iter_type      (a)                       ,ios_base&#38;     (b)                       ,char_type     (c)                       ,const tm*     (d)                       ,char)         (e)</PRE><UL>The types <SAMP>iter_type</SAMP> and <SAMP>char_type</SAMP> stand for the types that were provided as template arguments when the facet class was instantiated.  In this case, they are ostreambuf_iterator&#60;charT,traits></SAMP> and <SAMP>charT</SAMP>, where <SAMP>charT</SAMP> and <SAMP>traits</SAMP> are the respective streams template arguments.<BR><BR><SAMP>Here is the actual call:</SAMP><BR><BR><SAMP>nextpos = fac.put(os,os,os.fill(),&#38;date,'x');</SAMP><BR><BR>Now let's see what the arguments mean:<BR><BR><OL><LI><P>The first parameter is supposed to be an output iterator.  We provide an iterator to the stream's underlying stream buffer.  The reference <SAMP>os</SAMP> to the output stream is converted to an output iterator, because output stream buffer iterators have a constructor taking an output stream, that is, <SAMP>basic_ostream&#60;charT,traits>&#38;</SAMP>.</P></LI><LI><P>The second parameter is of type <SAMP>ios_base&#38;,</SAMP> which is one of the stream base classes.  The class <SAMP>ios_base</SAMP> contains data for format control (see the section on iostreams for details).  The facet object uses this formatting information.  We provide the output stream's <SAMP>ios_base</SAMP> part here, using the automatic cast from a reference to an output stream, to a reference to its base class.</P></LI><LI><P>The third parameter is the fill character.  It is used when the output has to be adjusted and blank characters have to be filled in.  We provide the stream's fill character, which one can get by calling the stream's <SAMP>fill()</SAMP> function.</P></LI><LI><P>The fourth parameter is a pointer to a time structure <SAMP>tm</SAMP> from the C library.</P></LI><LI><P>The fifth parameter is a format character as in the C function <SAMP>strftime()</SAMP>; the <SAMP>x</SAMP> stands for the locale's appropriate date representation.</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -