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

📄 use_1194.htm

📁 C++标准库 C++标准库 C++标准库 C++标准库
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD><TITLE>1.6 User-Defined Facets:  An Example</TITLE></HEAD><BODY><A HREF="ug2.htm"><IMG SRC="images/banner.gif"></A><BR><A HREF="fac_3537.htm"><IMG SRC="images/prev.gif"></A><A HREF="booktoc2.htm"><IMG SRC="images/toc.gif"></A><A HREF="str_8843.htm"><IMG SRC="images/next.gif"></A><BR><STRONG>Click on the banner to return to the user guide home page.</STRONG><H2>1.6 User-Defined Facets:  An Example</H2><P>The previous sections explained how to use locales and the standard facet classes, and how you can build new facet classes.  This section introduces you to the technique of building your own facet class and using it in conjunction with the input/output streams of the Standard C++ Library, the iostreams.  This material is rather advanced, and requires some knowledge of standard iostreams.</P><P>In the following pages, we will work through a complete example on formatting telephone numbers.  Formatting telephone numbers involves local conventions that vary from culture to culture.  For example, the same US phone number can have all of the formats listed below:</P><CENTER><TABLE CELLSPACING=3 CELLPADDING=3><TR VALIGN=top><TD>754-3010<BR></TD><TD>Local<BR></TD></TR><TR VALIGN=top><TD> (541) 754-3010<BR></TD><TD>Domestic<BR></TD></TR><TR VALIGN=top><TD>+1-541-754-3010<BR></TD><TD>International<BR></TD></TR><TR VALIGN=top><TD>1-541-754-3010<BR></TD><TD>Dialed in the US<BR></TD></TR><TR VALIGN=top><TD>001-541-754-3010<BR></TD><TD>Dialed from Germany<BR></TD></TR><TR VALIGN=top><TD>191 541 754 3010<BR></TD><TD>Dialed from France<BR></TD></TR></TABLE></CENTER><P>Now consider a German phone number.  Although a German phone number consists of an area code and an extension like a US number, the format is different.  Here is the same German phone number in a variety of formats:</P><CENTER><TABLE CELLSPACING=3 CELLPADDING=3><TR VALIGN=top><TD>636-48018<BR></TD><TD>Local<BR></TD></TR><TR VALIGN=top><TD>(089) / 636-48018<BR></TD><TD>Domestic<BR></TD></TR><TR VALIGN=top><TD>+49-89-636-48018<BR></TD><TD>International<BR></TD></TR><TR VALIGN=top><TD>19-49-89-636-48018<BR></TD><TD>Dialed from France<BR></TD></TR></TABLE></CENTER><P>Note the difference in formatting domestic numbers.  In the US, the convention is <SAMP>1 (area code) extension</SAMP>, while in Germany it is <SAMP>(0 area code)/extension</SAMP>.</P><A NAME="1.6.1"><H3>1.6.1 A Phone Number Class</H3></A><P>An application that has to handle phone numbers will probably have a class that represents a phone number.  We will also want to read and write telephone numbers via iostreams, and therefore define suitable extractor and inserter functions.  For the sake of simplicity, we will focus on the inserter function in our example.</P><P>To begin, here is the complete class declaration for the telephone number class <SAMP>phoneNo</SAMP>:</P><PRE>class phoneNo{public: typedef basic_ostream&#60;char> outStream_t; typedef string string_t; phoneNo(const string_t&#38; cc,const string_t&#38; ac,const string_t&#38; ex)    : countryCode(cc), areaCode(ac), extension(ex) {}private:   string_t countryCode;                                     //"de"   string_t areaCode;                                        //"89"   string_t extension;                                //"636-48018"friend phoneNo::outStream_t&#38; operator&#60;&#60;   (phoneNo::outStream_t&#38;, const phoneNo&#38;);};</PRE><A NAME="1.6.2"><H3>1.6.2 A Phone Number Formatting Facet Class</H3></A><P>Now that we have locales and facets in C++, we can encapsulate the locale-dependent parsing and formatting of telephone numbers into a new facet class.  Let's focus on formatting in this example.  We will call the new facet class <SAMP>phone_put</SAMP>, analogous to <SAMP>time_put</SAMP>, <SAMP>money_put</SAMP>, etc.</P><P>The <SAMP>phone_put</SAMP> facet class serves solely as a base class for facet classes that actually implement the locale-dependent formatting.  The relationship of class <SAMP>phone_put</SAMP> to the other facet classes is illustrated in Figure 14:</P><H4>Figure 14.  The relationship of the <SAMP>phone_put</SAMP> facet to the implementing facets</H4><BR><IMG SRC="images/image14.gif"><P>Here is a first tentative declaration of the new facet class <SAMP>phone_put</SAMP>:</P><PRE>class phone_put: public locale::facet                        //1{public:   static locale::id id;                                     //2   phone_put(size_t refs = 0) : locale::facet(refs) { }      //3   string_t put(const string_t&#38; ext               ,const string_t&#38; area                ,const string_t&#38; cnt) const;                  //4};</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>Derive from the base class <SAMP>locale::facet</SAMP>, so that a locale object will be able to maintain instances of our new phone facet class.</TD></TR><TR VALIGN="top"><TD>//2</TD><TD>New facet classes need to define a static data member <SAMP>id</SAMP> of type <SAMP>locale::id</SAMP>.</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>Define a constructor that takes the reference count that will be handed over to the base class.</TD></TR><TR VALIGN="top"><TD>//4</TD><TD>Define a function <SAMP>put()</SAMP> that does the actual formatting.</TD></TR></TABLE><A NAME="1.6.3"><H3>1.6.3 An Inserter for Phone Numbers</H3></A><P>Now let's take a look at the implementation of the inserter for our phone number class:</P><PRE>ostream&#38; operator&#60;&#60;(ostream&#38; os, const phoneNo&#38; pn){  locale loc = os.getloc();                                    //1 const phone_put&#38; ppFacet = use_facet&#60;phone_put> (loc);       //2 os &#60;&#60; ppFacet.put(pn.extension, pn.areaCode, pn.countryCode);//3 return (os);}</PRE><TABLE CELLPADDING="3"><TR VALIGN="top"><TD>//1</TD><TD>The inserter function will use the output stream's locale object (obtained via <SAMP>getloc()</SAMP>), </TD></TR><TR VALIGN="top"><TD>//2</TD><TD>use the locale's phone number facet object,</TD></TR><TR VALIGN="top"><TD>//3</TD><TD>and call the facet object's formatting service <SAMP>put()</SAMP>.</TD></TR></TABLE><A NAME="1.6.4"><H3>1.6.4 The Phone Number Facet Class Revisited</H3></A><P>Let us now try to implement the phone number facet class.  What does this facet need to know?</P><UL><LI><P>A facet needs to know its own locality, because a phone number is formatted differently for domestic and international use; for example, a German number looks like (089) / 636-48018 when used in Germany, but it looks like +1-49-89-636-48018 when used internationally.</P></LI><LI><P>A facet needs information about the prefix for dialing international numbers; for example, 011 for dialing foreign numbers from the US, or 00 from Germany, or 19 from France.</P></LI><LI><P>A facet needs access to a table of all country codes, so that one can enter a mnemonic for the country instead of looking up the respective country code.  For example, I would like to say:  "This is a phone number somewhere in Japan" without having to know what the country code for Japan is.</P></LI></UL><A NAME="1.6.4.1"><H4>1.6.4.1 Adding Data Members</H4></A><P>The following class declaration for the telephone number formatting facet class is enhanced with data members for the facet object's own locality, and its prefix for international calls (see <SAMP>//2</SAMP> and <SAMP>//3</SAMP> in the code below).  Adding a table of country codes is omitted for the time being.</P><PRE>class phone_put: public locale::facet {public:  typedef string string_t;  static locale::id id;  phone_put(size_t refs = 0) : locale::facet(refs)                             , myCountryCode_("")                             , intlPrefix_("")      {  } string_t put(const string_t&#38; ext,               const string_t&#38; area,               const string_t&#38; cnt) const;protected:  phone_put( const string_t&#38; myC                              //1           , const string_t&#38; intlP           , size_t refs = 0)           : locale::facet(refs)           , myCountryCode_(myC)           , intlPrefix_(intlP)   {  }  const string_t myCountryCode_;                              //2  const string_t intlPrefix_;                                 //3};</PRE><P>Note how this class serves as a base class for the facet classes that really implement a locale-dependent phone number formatting.  Hence, the public constructor does not need to be extended, and a protected constructor is added instead (see <SAMP>//1</SAMP> above).</P><A NAME="1.6.4.2"><H4>1.6.4.2 Adding Country Codes</H4></A><P>Let us now deal with the problem of adding the international country codes that were omitted from the previous class declaration.  These country codes can be held as a map of strings that associates the country code with a mnemonic for the country's name, as shown in Figure 15:</P><H4>Figure 15.  Map associating country codes with mnemonics for countries' names</H4><BR><IMG SRC="images/image15.gif"><P>In the following code, we add the table of country codes:</P><PRE>class phone_put: public locale::facet { public:   class prefixMap_t : public map&#60;string,string>             //1   {     public:       prefixMap_t() { insert(tab_t(string("US"),string("1")));        insert(tab_t(string("De"),string("49")));       // ...   }};   static const prefixMap_t* std_codes()                     //2          { return &#38;stdCodes_; } protected:   static const prefixMap_t stdCodes_;                       //3};</PRE><P>As the table of country codes is a constant table that is valid for all telephone number facet objects, it is added as a static data member <SAMP>stdCodes_</SAMP> (see <SAMP>//3</SAMP>).  The initialization of this data member is encapsulated in a class, <SAMP>prefixMap_t</SAMP> (see <SAMP>//1</SAMP>).  For convenience, a function <SAMP>std_codes()</SAMP> is added to give access to the table (see <SAMP>//2</SAMP>).</P>

⌨️ 快捷键说明

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