Wednesday, February 5, 2025

num_get, num_put and numpunct facets

Overview
CRT provides apis for reading and formatting numbers with various punctuations. Standard library provides same functionality using num_get, num_put and time_punct facets.

Details

num_get
This class encapsulates number parsing rules. The instream manipulators use the num_get facet of the I/O stream's locale to convert text input to a number.

Syntax
template<class CharT,class InputIt = std::istreambuf_iterator<CharT>> 
class time_get: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. Aliased as member iter_type.

Specializations
//narrow string representations of numbers
num_get<char>

//wide string representations of numbers
num_get<wchar_t>	

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

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

Methods
conversion functions
NameDescription
iter_type get
(iter_type begiter_type end, ios_base& str, 
ios_base::iostate& err, xxx& val)
Reads successive characters from the sequence [beg, end] and parses out the number. The parsed number is stored in the val.
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.
The xxx can be any of the following:
boolvoid* short  unsigned short
int unsigned int long unsigned long
long long unsigned long long float double
long double
Example
{
    locale l("en_US.utf-8");
    istringstream number ("3.14159");
    number.imbue(l);
    ios_base::iostate err = ios_base::goodbit;
    auto& numf = use_facet<num_get<char> > (l);
    num_get<char>::iter_type end;
    double pi;
    //itr:end
    //err:ios_base::eofbit;
    //prints:3.14159
    auto itr = numf.get({number}, end, number, err, pi);
    cout << pi << endl;
}

{
    locale l("de_DE.utf-8");
    istringstream number ("3,14159");
    number.imbue(l);
    ios_base::iostate err = ios_base::goodbit;
    
    auto& numf = use_facet<num_get<char> > (l);
    num_get<char>::iter_type end;
    double pi;
    //itr:end
    //err:ios_base::eofbit;
    //prints:3.14159
    auto itr = numf.get({number}, end, number, err, pi);
    cout << pi << endl;
}
This example 10  parses a string containing a double in the native format of the various locales using numget facet as seen in its console output.

num_put
This class encapsulates number formatting rules. The I/O manipulator for numbers uses the num_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 num_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. Aliased as member iter_type.

Specializations
//narrow string representations of date and time
num_put<char>

//wide string representations of date and time
num_put<wchar_t>	

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

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

Methods
NameDescription
iter_type put
(iter_type outios_base& str,char_type fill,
xxx val)
Writes numerical value in val to the stream pointer out. fill is used for  padding.
The streams io flags are honoured. 
The xxx can be any of the following:
boolvoid* short  unsigned short
int unsigned int long unsigned long
long long unsigned long long float double
long double
Example
double pi{3.14159};
{
    locale l("en_US.utf-8");
    cout.imbue(l);
    auto& numf = use_facet<num_put<char> > (l);
    //itr:end
    //prints:0003.14159
    cout << setw(10);
    numf.put(cout, cout, '0', pi);
    cout << endl;
}

{
    locale l("de_DE.utf-8");
    cout.imbue(l);
    auto& numf = use_facet<num_put<char> > (l);
    cout << setprecision (3);
    cout << setw(5);
    //itr:end
    //prints:03,14
    numf.put(cout, cout, '0', pi);
}
This example 11 demonstrate writing a double under various locales using numput facet as seen in
 its console output.

numpunct
The numpunct standard facet provides information about the format of punctuation marks for numbers and also the strings to represent the true and false boolean values.

Syntax
template<class CharT>> 
class num_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.

Specializations
//narrow string representations 
num_punct<char>

//wide string representations of date and time
num_punct<wchar_t>	

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

Constructor
NameDescription
num_punct(size_t refs = 0)Creates a num_punct 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.
Example
{
    locale l("en_US.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:.
    auto ch = npunct.decimal_point();
    cout << ch << endl;
}
{
    locale l("de_DE.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:,
    auto ch = npunct.decimal_point();
    cout << ch << endl;
}
char_type thousands_sep()
Returns the character used to represent the digit group separator.
Example
{
    locale l("en_US.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:,
    auto ch = npunct.thousands_sep();
    cout << ch << endl;
}

{
    locale l("de_DE.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:.
    auto ch = npunct.thousands_sep();
    cout << ch << endl;
}
 
string 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.
Example
   {
    locale l("en_US.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:3 3
    auto s = npunct.grouping();
    for (auto c:s) cout << static_cast<int>(c) << " ";
    cout <<  endl;
}
{
    locale l("ja_JP.utf-8");
    auto& npunct = use_facet <numpunct<char> > (l);
    //prints:3
    auto s = npunct.grouping();
    for (auto c:s) cout << static_cast<int>(c) << " ";
    cout <<  endl;
}
string truename()
string falsename()
Returns the string used to represent the boolean value true and false.
Example
struct custom_tf : numpunct<char>
{
    std::string do_truename()  const { return {"ಸತ್ಯ"}; }
    std::string do_falsename() const { return {"ಮಿಥ್ಯ"}; }
};
 
    {
        auto& npunct = use_facet <numpunct<char> > (locale());
        //prints:true false
        cout << npunct.truename() << " " << npunct.falsename() << endl;
    }
    {
        locale l(locale(),new custom_tf());
        auto& npunct = use_facet <numpunct<char> > (l);
        //prints:ಸತ್ಯ ಮಿಥ್ಯ
        cout << npunct.truename() << " " << npunct.falsename() << endl;
    }
This example 12 lists  the native numeric punctuation of the various locales using numpunct facet as seen its console output.




No comments:

Post a Comment