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

📄 fac_3537.htm

📁 C++标准库 C++标准库 C++标准库 C++标准库
💻 HTM
📖 第 1 页 / 共 2 页
字号:
</LI><LI><P>The value returned is an output iterator that points to the position immediately after the last inserted character. </P></LI></OL></UL><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//8</TD><TD>As we work with output stream buffer iterators, we can even check for errors happening during the time formatting.  Output stream buffer iterators are the only iterators that have a member function <SAMP>failed()</SAMP> for error indication. <A HREF="endnote2.htm#fn11">[11]</A></TD></TR><TR VALIGN="top"><TD>//9</TD><TD>If there was an error, we set the stream's state accordingly.  See the section on iostreams for details on the <SAMP>setstate()</SAMP> function and the state bits.</TD></TR></TABLE><A NAME="1.5.4"><H3>1.5.4 Creating a Facet Class for Replacement in a Locale</H3></A><P>At times you may need to replace a facet object in a locale by another kind of facet object.  In the following example, let us derive from one of the standard facet classes, <SAMP>numpunct</SAMP>, and create a locale object in which the standard <SAMP>numpunct</SAMP> facet object is replaced by an instance of our new, derived facet class. </P><P>Here is the problem we want to solve.  When you print boolean values, you can choose between the numeric representation of the values <SAMP>"true"</SAMP> and <SAMP>"false"</SAMP>, or their alphanumeric representation. </P><PRE>int main(int argc, char** argv){   bool any_arguments = (argc > 1);                           \\1   cout.setf(ios_base::boolalpha);                            \\2   cout &#60;&#60; any_arguments &#60;&#60; '\n';                             \\3   // _}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>A variable of type <SAMP>bool</SAMP> is defined.  Its initial value is the boolean value of the logical expression <SAMP>(argc > 1)</SAMP>, so the variable <SAMP>any_arguments</SAMP> contains the information, whether the program was called with or without arguments.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The format flag <SAMP>ios_base:: boolalpha</SAMP> is set in the predefined output stream <SAMP>cout</SAMP>.  The effect is that the string representation of boolean values is printed, instead of their numerical representation <SAMP>0</SAMP> or <SAMP>1</SAMP>, which is the default representation.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>Here either the string <SAMP>"true"</SAMP> or the string <SAMP>"false"</SAMP> will be printed.</TD></TR></TABLE><P>Of course, the string representation depends on the language.  Hence, the alphanumeric representation of boolean values is provided by a locale.  It is the <SAMP>numpunct</SAMP> facet of a locale that describes the cultural conventions for numerical formatting.  It has a service that provides the string representation of the boolean values <SAMP>true</SAMP> and <SAMP>false</SAMP>.<A HREF="endnote2.htm#fn12">[12]</A></P><P>This is the interface of facet <SAMP>numpunct</SAMP>:</P><PRE>template &#60;class charT>    class numpunct : public locale::facet {    public:      typedef charT               char_type;      typedef basic_string&#60;charT> string_type;      explicit numpunct(size_t refs = 0);      string_type  decimal_point()   const;      string_type  thousands_sep()   const;      vector&#60;char> grouping()        const;      string_type  truename()        const;      string_type  falsename()       const;      static locale::id id;};</PRE><P>Now let us replace this facet.  To make it more exciting, let's use not only a different language, but also different words for <SAMP>true</SAMP> and <SAMP>false</SAMP>, such as <SAMP>Yes!</SAMP> and <SAMP>No!</SAMP>.  For just using another language, we would not need a new facet; we would simply use the right native locale, and it would contain the right facet.</P><PRE>template &#60;class charT, charT* True, charT* False>             //1class CustomizedBooleanNames : public numpunct_byname&#60;charT> {                             //2    typedef basic_string&#60;charT> string;  protected:    string do_truename()  {return True;}                      //3    string do_falsename() {return False;}    ~CustomizedBooleanNames() {}  public:    explicit CustomizedBooleanNames(const char* LocName)      //4         : numpunct_byname&#60;charT>(LocName) {}};</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>The new facet is a class template that takes the character type as a template parameter, and the string representation for <SAMP>true</SAMP> and <SAMP>false</SAMP> as non-type template parameters.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The new facet is derived from the <SAMP>numpunct_byname&#60;charT></SAMP> facet.<BR><BR>The byname facets read the respective locale information from the external representation of a C locale.  The name provided to construct a byname facet is the name of a locale, as you would use it in a call to <SAMP>setlocale()</SAMP>.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>The virtual member functions <SAMP>do_truename()</SAMP> and <SAMP>do_falsename()</SAMP> are<SAMP> </SAMP>reimplemented.  They are called by the public member functions <SAMP>truename()</SAMP> and <SAMP>falsename()</SAMP>.  See the <I>Class</I> <I>Reference</I> for further details.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>A constructor is provided that takes a locale name.  This locale's <SAMP>numpunct</SAMP> facet will be the basis for our new facet.</TD></TR></TABLE><P>Now let's replace the <SAMP>numpunct</SAMP> facet object in a given locale object, as shown in Figure 12:</P><H4>Figure 12.  Replacing the numpunct facet object</H4><BR><IMG SRC="images/image12.gif"><P>The code looks like this:</P><PRE>char Yes[] = "Ja.";char No[] = "Nein.";void main(int argc, char** argv){  locale loc(locale("de_DE"),                                 \\1       new CustomizedBooleanNames&#60;char,Yes,No>("de_DE"));     \\2  cout.imbue(loc);                                            \\3  cout &#60;&#60; "Argumente vorhanden? "  //Any arguments?       &#60;&#60; boolalpha &#60;&#60; (argc > 1) &#60;&#60; endl;                    \\4}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>A locale object is constructed with an instance of the new facet class.  The locale object will have all facet objects from a German locale object, except that the new facet object <SAMP>CustomizedBooleanNames</SAMP> will substitute for the <SAMP>numpunct</SAMP> facet object.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>The new facet object takes all information from a German <SAMP>numpunct</SAMP> facet object, and replaces the default native names <SAMP>true</SAMP> and <SAMP>false</SAMP> with the provided strings <SAMP>"Ja."</SAMP>("Yes.") and <SAMP>"Nein."</SAMP>("No.").<BR><BR>Note that the facet object is created on the heap.  That's because the <SAMP>locale</SAMP> class by default manages installation, reference-counting, and destruction of all its facet objects.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>The standard output stream <SAMP>cout</SAMP> is imbued with the newly created locale object.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>The expression <SAMP>(argc > 1)</SAMP> yields a boolean value, which indicates whether the program was called with arguments.  This boolean value's alphanumeric representation is printed to the standard output stream.  The output might be:<BR><BR><SAMP>Argument vorhanden? Ja.</SAMP></TD></TR></TABLE><A NAME="1.5.5"><H3>1.5.5 The Facet Id</H3></A><P>In the example discussed above, we derived a new facet class from one of the standard facet classes, then replaced an object of base class type by one of derived class type.  The inheritance relationship of the facet classes is essential if you plan on replacing facet objects.  Let us see why this is true.</P><P>A locale object maintains a set of facet objects.  Each facet object has an identification that serves as an index to the set of facet objects.  This identification, called <SAMP>id,</SAMP> is a static data member of the respective facet class.  Whether or not a facet object will replace another facet, or be an actual addition to the locale object's set of facet objects, solely depends on the facet's identification.</P><P>The base class of all facets, class <SAMP>locale::facet</SAMP>, does not have a facet identification.  The class <SAMP>locale::facet</SAMP> performs the function of an abstract base class; there will never be any facet object of the base class type.  However, all concrete facet classes have to define a facet identification.  In the example above, we inherited the facet identification from the base class we derived from, that is, the standard facet class <SAMP>numpunct</SAMP>.  Every object of our facet class <SAMP>CustomizedBooleanNames</SAMP> has a facet identification that identifies it as a <SAMP>numpunct</SAMP> facet.  As the facet identification serves as an index to the locale object's set of facets, our facet object replaced the current <SAMP>numpunct</SAMP> facet object in the locale object's set of facet objects.</P><P>If you do not want to replace a facet object, but want to add a new kind of facet object, we have to provide it with a facet identification different from all existing facet identifications.  The following example will demonstrate how this can be achieved.</P><A NAME="1.5.6"><H3>1.5.6 Creating a Facet Class for Addition to a Locale</H3></A><P>At times you may need to add a facet object to a locale.  This facet object must have a facet identification that distinguishes it from all existing kinds of facets.</P><P>Here is an example of a new facet class like that.  It is a facet that checks whether a given character is a German umlaut<A HREF="endnote2.htm#fn13">[13]</A>, that is, one of the special characters <IMG SRC="images/inline4.gif">.</P><PRE>class Umlaut : public locale::facet {                         \\1  public:    static locale::id id;                                     \\2    bool is_umlaut(char c);                                   \\3    Umlaut() {}  protected:    ~Umlaut() {}};</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>All facet classes have to be derived from class <SAMP>locale::facet</SAMP>.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>Here we define the static data member <SAMP>id</SAMP>.  It is of type <SAMP>locale::id</SAMP>.  The default constructor of the facet identification class <SAMP>locale::id</SAMP> assigns the next unused identification to each object it creates.  Hence, it is not necessary, nor even possible, to explicitly assign a value to the static facet <SAMP>id</SAMP> object.  In other words, this definition does the whole trick; our facet class will have a facet identification that distinguishes it from all other facet classes.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>A member function <SAMP>is_umlaut()</SAMP> is declared that returns <SAMP>true</SAMP> if the character is a German umlaut. </TD></TR></TABLE><P>Now let's add the new facet object to a given locale object, as shown in Figure 13:</P><H4>Figure 13.  Adding a new facet to a locale</H4><BR><IMG SRC="images/image13.gif"><P>The code for this procedure is given below:</P><PRE>locale loc(locale(""),  // native locale           new Umlaut); // the new facet                      //1char c,d;while (cin >> c){ d = use_facet&#60;ctype&#60;char> >(loc).tolower(c);                 //2 if (has_facet&#60;Umlaut>(loc))                                  //3 { if (use_facet&#60;Umlaut>(loc).is_umlaut(d))                   //4       cout &#60;&#60; c &#60;&#60; "belongs to the German alphabet!" &#60;&#60; '\n'; }}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>A locale object is constructed with an instance of the new facet class.  The locale object will have all facet objects from the native locale object, plus an instance of the new facet class <SAMP>Umlaut</SAMP>.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>Let's assume our new umlaut facet class is somewhat limited; it can handle only lower case characters.  Thus we have to convert each character to a lower case character before we hand it over to the umlaut facet object.  This is done by using a <SAMP>ctype</SAMP> facet object's service function<SAMP> tolower()</SAMP>.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>Before we use the umlaut facet object, we check whether such an object is present in the locale.  In a toy example like this it is obvious, but in a real application it is advisable to check for the existence of a facet object, especially if it is a non-standard facet object we are looking for.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>The umlaut facet object is used, and its member function <SAMP>is_umlaut()</SAMP> is called.  Note that the syntax for using this newly contrived facet object is exactly like the syntax for using the standard <SAMP>ctype</SAMP> facet.</TD></TR></TABLE><HR><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><P>&copy;Copyright 1996, Rogue Wave Software, Inc.</P></BODY></HTML>

⌨️ 快捷键说明

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