Showing posts with label Localization. Show all posts
Showing posts with label Localization. Show all posts

Wednesday, February 12, 2025

Unicode conversion facets

Overview
The following are Codecvt based facets to convert Unicode based formats with each other. For example, conversion from  UTF-8 to UCS-2, UTF-16 and UTF-32. Also reverse.

Details


codecvt_mode
This is a bitmask based enum defined as below:
enum codecvt_mode {  consume_header = 4,  generate_header = 2,  little_endian = 1}.
Note that 0 is also a valid value that represents the absence of all flags.

The facets codecvt_utf8, codecvt_utf16, and codecvt_utf8_utf16 accept an optional value of type codecvt_mode as a template argument, which specifies optional features of the unicode string conversion.
NameDescription
little_endian Assume the input is in little-endian byte order (applies to UTF-16 input only, the default is big-endian).
generate_header Output the BOM at the start of the output sequence.
consume_header Consume the BOM, if present at the start of input sequence, and (in case of UTF-16), rely on the byte order it specifies for decoding the rest of the input.

BOM types
BOM is basically a set of characters present in a UTF stream that determines its nature of origin.
NameValues
UTF-16 big-endian0xfe 0xff
UTF-16 little-endian0xff 0xfe
UTF-80xef 0xbb 0xbf

Example
    ofstream{"text.txt"} << "\xef\xbb\xbfಖ್ರಿಷಾ Rao👸";
 
    // read the UTF-8 file, skipping the BOM
    wifstream fin{"text.txt"};
    fin.imbue(locale(fin.getloc(),
        new codecvt_utf8<wchar_t, 0x10ffff, consume_header>));
 
    istream_iterator<wchar_t, wchar_t> it(fin), end;
    cout << showbase << hex; 
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x52 0x61 0x6f 0x1f478 0 
    for_each(it,end, [](wchar_t c){cout << (unsigned long long)c << ' '; }

codecvt_utf8
codecvt_utf8 is a codecvt facet which encapsulates conversion between a UTF-8 encoded byte string and UCS-2 or UCS-4(UTF-32) character string (depending on the type of Elem). This codecvt facet can be used to read and write UTF-8 files, both text and binary.
Note that UCS-2 has limited code points (0xFFFF), unsuitable in some cases.

Syntax
template<
    class Elem,
    unsigned long Maxcode = 0x10ffff,
    codecvt_mode Mode = (codecvt_mode)0 >
class codecvt_utf8
    : public std::codecvt<Elem, char, std::mbstate_t>;

template parameters
NameDescription
Elem  Aliased as member intern_type. This can be: wchar_t, char16_t or char32_t.
MaxCode The largest code point that will be translated without reporting a conversion error.
Mode A constant of type codecvt_mode.

member types
NameDescription
intern_typeElem
extern_typechar
state_typecodecvt::state_type
resultcodecvt_base::result

Example
    char str8[] = u8"ಖ್ರಿಷಾ Rao👸";
    wstring_convert<codecvt_utf8<char32_t>, char32_t> u8to32;
    u32string str32 = u8to32.from_bytes(str8);
    cout << std::showbase << std::hex;
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x20 0x52 0x61 0x6f 0x1f478 
    for (char32_t c : str32)
        cout << static_cast<unsigned long long>(c) << ' ';

codecvt_utf16
codecvt_utf16 is a codecvt facet which encapsulates conversion between a UTF-16 encoded byte string and UCS-2 or UTF-32 character string (depending on the type of Elem). This codecvt facet can be used to read and write UTF-16 files in binary mode.

Syntax
template<
    class Elem,
    unsigned long Maxcode = 0x10ffff,
    std::codecvt_mode Mode = (std::codecvt_mode)0 >
class codecvt_utf16
    : public std::codecvt<Elem, char, std::mbstate_t>;

template parameters
NameDescription
Elem  Aliased as member intern_type. This can be: wchar_t, char16_t or char32_t.
MaxCode The largest code point that will be translated without reporting a conversion error.
Mode A constant of type codecvt_mode.

member types
NameDescription
intern_typeElem
extern_typechar
state_typecodecvt::state_type
resultcodecvt_base::result

Example
    char16_t utf16le[] = u"ಖ್ರಿಷಾ Rao👸";
    ofstream oss("test.txt");
    oss.write(reinterpret_cast<char*>(utf16le), sizeof utf16le);
    oss.close();

    wifstream wiss("test.txt",ios::binary|ios_base::in);
    wiss.imbue(locale(wiss.getloc(), new codecvt_utf16<wchar_t, 0x10ffff, little_endian>));
    istream_iterator<wchar_t, wchar_t> oit(wiss), end;
    cout << showbase << hex; 
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x52 0x61 0x6f 0x1f478 0 
    for_each(oit,end, [](wchar_t c){cout << (unsigned long long)c << ' '; });
    

codecvt_utf8_utf16
codecvt_utf8_utf16 is a codecvt facet which encapsulates conversion between a UTF-8 encoded byte string and UTF-16 encoded character string. If Elem is a 32-bit type, one UTF-16 code unit will be stored in each 32-bit character of the output sequence.
The UTF-16 string is variable width encoded so it can represent all the code points,
This is an N:M conversion facet, and cannot be used with std::basic_filebuf (which only permits 1:N conversions, such as UTF-32/UTF-8, between the internal and the external encodings). This facet can be used with std::wstring_convert.

Syntax
template<
    class Elem,
    unsigned long Maxcode = 0x10ffff,
    std::codecvt_mode Mode = (std::codecvt_mode)0 >
class codecvt_utf8_utf16
    : public std::codecvt<Elem, char, std::mbstate_t>

template parameters
NameDescription
Elem  Aliased as member intern_type. This can be: wchar_t, char16_t or char32_t.
MaxCode The largest code point that will be translated without reporting a conversion error.
Mode A constant of type codecvt_mode.

member types
NameDescription
intern_typeElem
extern_typechar
state_typecodecvt::state_type
resultcodecvt_base::result

Example
    char str8[] = u8"ಖ್ರಿಷಾ Rao👸";
    wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> u8to16;
    u16string str16 = u8to16.from_bytes(str8);
    cout << std::showbase << std::hex;
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x20 0x52 0x61 0x6f 0xd83d 0xdc78
    for (char16_t c : str16)
        cout << static_cast<unsigned> (c) << ' ';     

Tuesday, February 11, 2025

wstring_convert and wbuffer_convert

Overview
Performs conversions between wide strings and byte strings (on either direction) using a conversion object of type Codecvt.

Details
wstring_convert
Performs conversions between wide strings and byte strings (on either direction) using a conversion object of type Codecvt.
The standard facets suitable for use with wstring_convert are codecvt_utf8 for UTF-8/UCS-2 and UTF-8/UCS-4 conversions and codecvt_utf8_utf16 for UTF-8/UTF-16 conversions.
It's behavior is similar tombsrtowcs() api
.
Syntax
template<
    class Codecvt,
    class Elem = wchar_t,
    class Wide_alloc = std::allocator<Elem>,
    class Byte_alloc = std::allocator<char>
> class wstring_convert;

template parameters
NameDescription
Codecvt Type of the conversion object: codecvt_utf8 for UTF-8/UCS-2 and UTF-8/UCS-4 conversions and codecvt_utf8_utf16 for UTF-8/UTF-16 conversions.
Elem Wide character type.
Wide_alloc Allocator for elements of type Elem. Defaults to: allocator<Elem>
Byte_alloc Allocator for elements of type charDefaults to: allocator<char>


member types
NameDescription
byte_stringbasic_string<char>
wide_string
basic_string<Elem>
state_typeCodecvt::state_type
int_typechar_traits<Elem>::int_type

Fields
NameDescription
byte_string byte_err_stringthe byte string to display on errors.
wide_string wide_err_stringthe wide string to display on errors.
Codecvt* cvtptra pointer to the allocated conversion object
state_type cvtstatethe conversion state object
size_t cvtcountthe conversion counts

Constructor
NameDescription
  1. wstring_convert() 
  2. wstring_convert
    (Codecvt* pcvt = Codecvt()) 
  3. wstring_convert
    (Codecvt* pcvt, state_type state)
  4. wstring_convert
    (const byte_string& byte_err,
    const wide_string& wide_err = wide_string())
  1. Default Constructor 
  2. Initialization constructor. Constructs an object that uses pcvt as conversion object with a default-constructed shift state.
  3. Initialization constructor with state. Constructs an object that uses pcvt as conversion object and state as the initial value for its shift state
  4. Constructor with error strings. Constructs an object that returns byte_err or wide_err on failure to convert, instead of throwing an exception. The object uses a conversion object automatically constructed with new Codecvt whose shift state is reset before every conversion operation.
Example
typedef codecvt_utf8<wchar_t> ccvt;

    //1
    wstring_convert<ccvt> wsc;
    //2
    wstring_convert<ccvt> wsc2 (new ccvt);
    //3
    wstring_convert<ccvt> wsc3 (new ccvt, ccvt::state_type());
    //4
    wstring_convert<ccvt> wsc4 ("[error]",L"[error]");

    wstring wstr (L"Khrisha Rao👸");
    //str:"Khrisha Rao👸"
    string str = wsc4.to_bytes (wstr);


Methods
NameDescription
  1. wide_string from_bytes
    (char byte)
  2. wide_string from_bytes
    (const char* ptr)
  3. wide_string  from_bytes
    (const byte_string& str)
  4. wide_string from_bytes
    (const char* first, const char* last )

  1. The byte sequence only consists of one element byte.
  2. The byte sequence is the null-terminated sequence beginning at ptr.
  3. The byte sequence is the sequence contained in str.
  4. The byte sequence is the range [first, last).
If the conversion succeeds, returns the conversion result. Otherwise, returns wide_err_string or throws an exception.
Example
char str8[] = u8"ಖ್ರಿಷಾ Rao👸";
    wstring_convert<codecvt_utf8<char32_t>, char32_t> u8to32;
    u32string str32 = u8to32.from_bytes(str8);
    cout << std::showbase << std::hex;
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x20 0x52 0x61 0x6f 0x1f478 
    for (char32_t c : str32)
        cout << static_cast<unsigned long long>(c) << ' ';
  1. byte_string to_bytes
    (Elem wchar)
  2. byte_string  to_bytes
    (
    const Elem* ptr)
  3. byte_string to_bytes
    (const wide_string& str)
  4. byte_string to_bytes
    (const Elem* first, const Elem* last )

  1. The wide sequence only consists of one element wchar.
  2. The wide sequence is the null-terminated sequence beginning at ptr.
  3. The wide sequence is the sequence contained in str.
  4. The wide sequence is the range [first, last).
If the conversion succeeds, returns the conversion result. Otherwise, returns wide_err_string or throws an exception.
Example
    char32_t str32[] = U"ಖ್ರಿಷಾ Rao👸";
    wstring_convert<codecvt_utf8<char32_t>, char32_t> uconv;
    string str8 = uconv.to_bytes(str32);
    //prints:ಖ್ರಿಷಾ Rao👸
    cout << str8 << endl;
size_t converted()Returns the number of input elements successfully converted by the last conversion operation.
state_type state()Returns the current value of the conversion state, which is stored in this wstring_convert object. The conversion state may be explicitly set in the constructor and is updated by all conversion operations.

wbuffer_convert
wbuffer_convert is a wrapper over stream buffer of type streambuf which gives it the appearance of basic_streambuf<Elem>.  
The class uses another stream buffer of bytes (narrow characters of type char) as its underlying byte stream buffer to/from which it converts wide characters of type Elem (its second template argument).
All I/O performed through wbuffer_convert undergoes character conversion as defined by the facet Codecvt. wbuffer_convert assumes ownership of the conversion facet, and cannot use a facet managed by a locale.
The standard facets suitable for use with std::wbuffer_convert are codecvt_utf8 for UTF-8/UCS-2 and UTF-8/UCS-4 conversions and std::codecvt_utf8_utf16 for UTF-8/UTF-16 conversions.
.
Syntax
template<
    class Codecvt,
    class Elem = wchar_t,
    class Tr = std::char_traits<Elem>
> class wbuffer_convert : public std::basic_streambuf<Elem, Tr>

template parameters
NameDescription
Codecvt Type of the conversion object: codecvt_utf8 for UTF-8/UCS-2 and UTF-8/UCS-4 conversions and codecvt_utf8_utf16 for UTF-8/UTF-16 conversions.
Elem Wide character type.
Tr   Character traits class

member types
NameDescription
state_typeCodecvt::state_type

Fields
NameDescription
streambuf* bufptra pointer to the underlying byte stream buffer.
Codecvt* cvtptra pointer to the allocated conversion object
state_type cvtstatethe conversion state object

Constructor
NameDescription
  1. wbuffer_convert() 
  2. wbuffer_convert
    (streambuf* bytebuf,
    Codecvt* pcvt = new Codecvt, 
    state_type state= state_type())
  1. Default Constructor 
  2. Initialization constructor.  Constructs a wbuffer_convert object with its internal state initialized to the arguments passed. The object wraps a bytebuf object, which becomes its underlying byte stream buffer.
Example
typedef codecvt_utf8<wchar_t> ccvt;

    //1
    wbuffer_convert<ccvt> wbuf;
    //2
    stringbuf utf8buf(reinterpret_cast<const char*>(u8"ಖ್ರಿಷಾ Rao👸"));
    wbuffer_convert<codecvt_utf8<wchar_t>> conv_in(&utf8buf);
    wistream ucsbuf(&conv_in);
    cout << hex << showbase;
    istreambuf_iterator<wchar_t> oit(ucsbuf), end;
    //prints:0xc96 0xccd 0xcb0 0xcbf 0xcb7 0xcbe 0x20 0x52 0x61 0x6f 0x1f478 
    for_each(oit,end, [](wchar_t c){cout << (unsigned long long)c << ' '; });
    cout << endl;


Methods
NameDescription
  1. streambuf* rdbuf() 
  2. streambuf* rdbuf
    (streambuf* bytebuf)

  1. Returns the pointer to the underlying byte stream.
  2. Replaces the associated byte stream with bytebuf.
Example
    //use clang
    wbuffer_convert<codecvt_utf8<wchar_t>> conv_out(cout.rdbuf());
    wostream out(&conv_out);
    //prints:ಖ್ರಿಷಾ Rao👸
    out << reinterpret_cast<const wchar_t*>(U"ಖ್ರಿಷಾ Rao👸");
state_type state()Returns the current value of the conversion state, which is stored in this wbuffer_convert object. The conversion state may be explicitly set in the constructor and is updated by all conversion operations.



Monday, February 10, 2025

messages facet

Overview
Message catalogs are basically string tables used by the operating systems to store system messages. 

Details
Message catalogs are stored under language specific subdirectories, under msg folder of the Operating system. There various tools such as gentext or gencat to create catalogs.

messages_base
This is a base classes messages facet. It defines the following member inherited by all the derived classes.
int catalog

messages
The messages standard facet is used to read individual strings from a message catalog.

Syntax
template<class CharT> 
class messages:public facet, public message_base
CharT can be char and whcar_t. It's aliased as member char_type.  It represents the type of the characters in the sequence to interpret.

Specializations
//narrow string representations of messages
messages<char>

//wide string representations of messages
messages<wchar_t>
Fields
NameDescription
locale::id id the identifier of the facet. Represents the messages category of the facet.

types
NameDescription
char_type Represents the character type. It's a typedef for CharT .
string_type Represents string type corresponding to the character type. 
It's a typedef for basic_string<charT>

Constructor
NameDescription
messages(size_t refs = 0)Creates a messages facet and forwards the starting reference count refs to the base class constructor, locale::facet::facet()

Methods
NameDescription
catalog open
(const string& name, const locale& loc) 
Opens the message catalog by name to access messages and returns an object that uniquely identifies the catalog when calling member messages::get.
Returns negative number upon failures.
char_type get
(catalog cat, int set, int msgid, const string_type& def )
Retrieves the message identified by set, msgid, and def in the catalog cat. If the message is not found, def is returned.
void close (catalog cat) 

Closes the opened catalog identified by cat.
Example
  





Friday, February 7, 2025

money_get,money_put and moneypunct facets

Overview
currency is a numerical values or strings of digits representing money. CRT provides apis for reading and formatting currency with various punctuations. Standard library provides same functionality using money_get, money_put and moneypunct facets. Thes are also used by IO stream manipulatprs money_get and money_put.

Details

money_base
This is a base class for money_get,  money_put and money_punct facets. These are internally used by  methods of the facets.

It defines part enum type  as below. 
enum part { none, space, symbol, sign, value };
NameDescription
none whitespace is permitted but not required except in the last position, where whitespace is not permitted
spaceone or more whitespace characters are required
symbolThe sequence of characters returned by moneypunct::curr_symbol is required
signThe first of the characters returned by moneypunct::positive_sign or moneypunct::negative_sign is required
valueThe absolute numeric monetary value is required

It also declares money format pattern as below.
struct pattern { char field[4]; }
The monetary format is an array of four chars convertible to enum part
In that sequence, each of symbol, sign, and value appears exactly once, and either space or none appears in the remaining position. 
The value none, if present, is not first; the value and space, if present, is neither first nor last.
The default format, returned by the standard specializations of moneypunct is {symbol, sign, none, value}.

money_get
This class encapsulates currency parsing rules. The iostream manipulator get_money use the money_get facet of the I/O stream's locale to convert text input to a currency.

Syntax
template<class CharT,class InputIt = std::istreambuf_iterator<CharT>> 
class money_get:public money_base, public facet
CharT can be char and whcar_t. It's aliased as member char_type.  It represents the type of the characters in the sequence to interpret.
InputIt Represents Input iterator type that points to the elements in the character sequence to interpret.
Defaults to istreambuf_iterator, which is an iterator that can be implicitly converted from basic_istream objects.

types
NameDescription
char_type Represents the character type. It's a typedef for CharT .
string_type Represents string type corresponding to the character type. 
It's a typedef for basic_string<charT>
iter_type Represents the iterator type. It's a typedef for InputIt.

Specializations
//narrow string representations of currency
money_get<char>

//wide string representations of currency
money_get<wchar_t>	

Fields
NameDescription
locale::id id the identifier of the facet. Represents the monitory category of the facet.
intlboolean value/ Alias of the second class template argument: International.

Constructor
NameDescription
money_get(size_t refs = 0)Creates a money_get facet and forwards the starting reference count refs to the base class constructor, locale::facet::facet()

Methods
NameDegcription
  1. iter_type get
    (iter_type begiter_type end,
    bool intl, ios_base& str,
    iostate& err, long double& val)
  2. iter_type get
    (iter_type begiter_type end, 
    bool intl, ios_base& str,
    iostate& err, string_type& val)

Reads successive characters from the sequence [beg, 
end] and parses out the currency. 
The parsed number is stored in the val.
intl is used to pull correct format from moneypunct facet.
If the end iterator is reached before a valid number is read, the function sets ios_base::eofbit in err. If a parsing error is encountered, the function sets ios_base::failbit in err.
Example
istringstream ss("USD  1,234.56");
ss.imbue(locale("en_US.UTF-8"));
 
auto& f = use_facet<money_get<char>>(ss.getloc());
ios_base::iostate err;
istreambuf_iterator<char> beg(ss), end;
    
long double val;

//val:123456
f.get(beg, end, true, ss, err, val);

string sval;
ss.str("$1,234.56");
//sval:"123456"
f.get(beg, end, false, ss, err, sval);
This example 7 demonstrates the usage of the money_get facet as seen in its console output.

money_put
This class encapsulates currency formatting rules. The I/O manipulator for currency put_money uses the money_put facet of the I/O stream's locale to generate text representing from numbers.

Syntax
template<class CharT,class OutputIt = std::ostreambuf_iterator<CharT>> 
class money_put:public facet
CharT can be char and whcar_t. It's aliased as member char_type.  It represents the type of the characters in the sequence to interpret.
OutputIt Represents Output iterator type that points to the output stream where text will be written.
Defaults to ostreambuf_iterator, which is an iterator that can be implicitly converted from basic_ostream objects. 

types
NameDescription
char_type Represents the character type. It's a typedef for CharT .
string_type Represents string type corresponding to the character type. 
It's a typedef for basic_string<charT>
iter_type Represents the iterator type. It's a typedef for InputIt.

Specializations
//narrow string representations of currency
money_put<char>

//wide string representations of currency
money_put<wchar_t>	

Fields
NameDescription
locale::id id the identifier of the facet. Represents the monitory category of the facet.

Constructor
NameDescription
money_put(size_t refs = 0)Creates a money_put facet and forwards the starting reference count refs to the base class constructor, locale::facet::facet().

Methods
NameDescription
  1. iter_type put
    (iter_type out, bool intl, ios_base& str,
    char_type fill, long double val)
  2. iter_type put
    (iter_type outbool intl, ios_base& str,
    char_type fill, string val)
Writes currency value in val to the stream pointer out. fill is used for  padding. intl used is formatting in conjunction with moneypunct facet.
The streams io flags are honoured. 
Example
    cout.imbue(locale("en_US.UTF-8"));
    auto& f = use_facet<money_put<char>>(cout.getloc());


    cout << setw(15) << right  << showbase;
    //prints:######$1,234.56
    f.put(cout, false, cout, '#', 123456);
    cout << endl;
    
    cout << setw(15) << right  << showbase;
    //prints:##USD #1,234.56
    f.put(cout, true, cout, '#', "123456");
This example 8 demonstrates the usage of the money_put facet apis as seen in its console output.

moneypunct
The facet moneypunct encapsulates monetary value format preferences. Stream I/O manipulators get_money and put_money use moneypunct through money_get and money_put for parsing monetary value input and formatting monetary value output.

Syntax
template <class charT, bool International = false>
class money_punct:public facet, public money_base
CharT can be char and whcar_t. It's aliased as member char_type.  It represents the type of the characters in the sequence to interpret.
International  If true, the representation uses an international format (such as using the three-letter code USD for the US dollar)
If false (the default value), the representation may use a non-international format (such as using the dollar sign, $, for the US dollar).

types
NameDescription
char_type Represents the character type. It's a typedef for CharT .
string_type Represents string type corresponding to the character type. 
It's a typedef for basic_string<charT>

Specializations
//narrow string representations 
moneypunct<char>

//narrow string representations with international currency symbols
moneypunct<char,true>

//wide string representations with international currency symbols
moneypunct<wchar_t>

//wide string representations with international currency symbols
moneypunct<wchar_t,true>

Fields
NameDescription
locale::id id the identifier of the facet. Represents the time category of the facet.

Constructor
NameDescription
moneypunct(size_t refs = 0)Creates a moneypunct facet and forwards the starting reference count refs to the base class constructor, locale::facet::facet().

Methods
NameDescription
char_type decimal_point()
Returns the character used to represent the decimal radix separator.
char_type thousands_sep()Returns the character used to represent the digit group separator.
string_type grouping()

Returns a sequence of values indicating the number of digits in each group.

Each char element in the returned sequence is shall be interpreted as an integer value indicating the number of digits in each group. Grouping is considered from right to left, with the first character in the string being used for the rightmost group, and the last character used for any group farther away than the length of the string.

For example, "\03" indicates groups of three digits each, while "\02\03" would indicate that the rightmost group has two digits and all the remaining ones have three digits each.
string_type curr_symbol() Returns the string used to represent the currency identifier symbol.
string_type positive_sign()Returns the string used to represent the indicate a monetary value is positive.
string_type negative_sign()Returns the string used to represent the indicate a monetary value is negative.
int frac_digits()Returns the number of digits after the decimal separator sign, if any.
int frac_digits()Returns the number of digits after the decimal separator sign, if any.
pattern pos_format()Returns the pattern that specifies the format for positive monetary expressions.
pattern neg_format()Returns the pattern that specifies the format for negative monetary expressions.
Example
ostream& operator<< (ostream& os, moneypunct<char>::pattern p)
{
    for (int i=0; i<4; i++)
    switch (p.field[i]) 
    {
      case moneypunct<char>::none: cout << "none "; break;
      case moneypunct<char>::space: cout << "space "; break;
      case moneypunct<char>::symbol: cout << "symbol "; break;
      case moneypunct<char>::sign: cout << "sign "; break;
      case moneypunct<char>::value: cout << "value "; break;
    }
  return os;
}


void printpunct (string loc)
{
  locale l(loc);
  
  cout.imbue(l);
  const moneypunct<char>& mp = use_facet<moneypunct<char> >(l);

  cout << "decimal_point: " << mp.decimal_point() << endl;
  cout << "thousands_sep: " << mp.thousands_sep() << endl;
  cout << "grouping: ";
  for (int c:mp.grouping()) cout << c << " ";
  cout << endl;
  cout << "curr_symbol: " << mp.curr_symbol() << endl;
  cout << "positive_sign: " << mp.positive_sign() << endl;
  cout << "negative_sign: " << mp.negative_sign() << endl;
  cout << "frac_digits: " << mp.frac_digits() << endl;
  cout << "pos_format: " << mp.pos_format() << endl;
  cout << "neg_format: " << mp.neg_format() << endl;
  cout << endl;
}


    /*prints 
    decimal_point: .
    thousands_sep: ,
    grouping: 3 3 
    curr_symbol: $
    positive_sign: 
    negative_sign: -
    frac_digits: 2
    pos_format: sign symbol value none 
    neg_format: sign symbol value none 
    */
    printpunct("en_US.utf8");
    
    /*prints 
    decimal_point: .
    thousands_sep: ,
    grouping: 3 
    curr_symbol: ¥
    positive_sign: 
    negative_sign: -
    frac_digits: 0
    pos_format: symbol sign value none 
    neg_format: symbol sign value none 
    */
    printpunct("ja_JP.utf8");
This example 9  demonstrates the usage of the moneypunct facet for different locales as seen in 
its console output.