std::num_put<CharT,OutputIt>::put, std::num_put<CharT,OutputIt>::do_put
| Definiert in Header <locale> |
||
| (1) | ||
| public: iter_type put( iter_type out, std::ios_base& str, |
||
| iter_type put( iter_type out, std::ios_base& str, char_type fill, long val ) const; |
||
| iter_type put( iter_type out, std::ios_base& str, char_type fill, long long val ) const; |
(seit C++11) | |
| iter_type put( iter_type out, std::ios_base& str, char_type fill, unsigned long val ) const; |
||
| iter_type put( iter_type out, std::ios_base& str, char_type fill, unsigned long long val ) const; |
(seit C++11) | |
| iter_type put( iter_type out, std::ios_base& str, char_type fill, double val ) const; |
||
| iter_type put( iter_type out, std::ios_base& str, char_type fill, long double val ) const; |
||
| iter_type put( iter_type out, std::ios_base& str, char_type fill, const void* val ) const; |
||
| (2) | ||
| protected: virtual iter_type do_put( iter_type out, std::ios_base& str, |
||
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long val ) const; |
||
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long long val ) const; |
(seit C++11) | |
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, unsigned long val ) const; |
||
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, unsigned long long val ) const; |
(seit C++11) | |
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, double val ) const; |
||
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long double val ) const; |
||
| virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, const void* val ) const; |
||
do_put der am weitesten abgeleiteten Klasse auf.Die Konvertierung erfolgt in vier Schritten
Inhalt |
[bearbeiten] Schritt 1: Auswahl des Konvertierungsspezifizierers
- Die I/O-Formatflags werden abgerufen, als ob durch
- fmtflags basefield = (str.flags() & std::ios_base::basefield);
- fmtflags uppercase = (str.flags() & std::ios_base::uppercase);
- fmtflags floatfield = (str.flags() & std::ios_base::floatfield);
- fmtflags showpos = (str.flags() & std::ios_base::showpos);
- fmtflags showbase = (str.flags() & std::ios_base::showbase);
- fmtflags showpoint = (str.flags() & std::ios_base::showpoint);
- Wenn der Typ von val bool ist
- Wenn boolalpha == 0, dann wird val in den Typ int konvertiert und die Integer-Ausgabe durchgeführt.
- Wenn boolalpha != 0, wird std::use_facet<std::numpunct<CharT>>(str.getloc()).truename() erhalten, wenn val == true oder std::use_facet<std::numpunct<CharT>>(str.getloc()).falsename() erhalten wird, wenn val == false, und jedes aufeinanderfolgende Zeichen c dieser Zeichenkette wird mit *out++ = c nach out ausgegeben. In diesem Fall erfolgt keine weitere Verarbeitung, und die Funktion gibt out zurück.
- Wenn der Typ von val ein Ganzzahltyp ist, wird die erste zutreffende Wahl aus den folgenden ausgewählt
- Wenn basefield == oct, wird der Konvertierungsspezifizierer %o verwendet.
- Wenn basefield == hex && !uppercase, wird der Konvertierungsspezifizierer %x verwendet.
- Wenn basefield == hex, wird der Konvertierungsspezifizierer %X verwendet.
- Wenn der Typ von val vorzeichenbehaftet ist, wird der Konvertierungsspezifizierer %d verwendet.
- Wenn der Typ von val vorzeichenlos ist, wird der Konvertierungsspezifizierer %u verwendet.
- Für Ganzzahltypen wird bei Bedarf ein Längenmodifikator zur Konvertierungsspezifikation hinzugefügt: l für long und unsigned long, ll für long long und unsigned long long(seit C++11).
- Wenn der Typ von val ein Fließkommatyp ist, wird die erste zutreffende Wahl aus den folgenden ausgewählt
|
(bis C++11) |
|
(seit C++11) |
- Wenn floatfield == std::ios_base::scientific && !uppercase, wird der Konvertierungsspezifizierer %e verwendet.
- Wenn floatfield == std::ios_base::scientific, wird der Konvertierungsspezifizierer %E verwendet.
|
(seit C++11) |
- Wenn !uppercase, wird der Konvertierungsspezifizierer %g verwendet.
- Andernfalls wird der Konvertierungsspezifizierer %G verwendet.
- Außerdem
- Wenn der Typ von val long double ist, wird der Längenmodifikator L zum Konvertierungsspezifizierer hinzugefügt.
- Wenn der Typ von val ein Fließkommatyp ist und floatfield != (ios_base::fixed | ios_base::scientific)(seit C++11), wird der Präzisionsmodifikator hinzugefügt und auf str.precision() gesetzt. Andernfalls wird keine Präzision angegeben.
- Für sowohl Ganzzahl- als auch Fließkommatypen wird, wenn showpos gesetzt ist, der Modifikator + vorangestellt.
- Für Ganzzahltypen wird, wenn showbase gesetzt ist, der Modifikator # vorangestellt.
- Für Fließkommatypen wird, wenn showpoint gesetzt ist, der Modifikator # vorangestellt.
- Wenn der Typ von val void* ist, wird der Konvertierungsspezifizierer %p verwendet.
- Eine schmale Zeichenkette wird erstellt, als ob durch einen Aufruf von std::printf(spec, val) in der "C"-Locale, wobei spec der gewählte Konvertierungsspezifizierer ist.
[bearbeiten] Schritt 2: Locale-spezifische Konvertierung
- Jedes Zeichen c, das in Schritt 1 erhalten wurde, mit Ausnahme des Dezimalpunkts '.', wird zu
CharTkonvertiert, indem std::use_facet<std::ctype<CharT>>(str.getloc()).widen(c) aufgerufen wird. - Für arithmetische Typen wird das Tausendertrennzeichen, erhalten von std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep(), gemäß den Gruppierungsregeln, die von std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping() bereitgestellt werden, in die Sequenz eingefügt.
- Dezimalpunktzeichen ('.') werden durch std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point() ersetzt.
[bearbeiten] Schritt 3: Auffüllen
- Das Ausrichtungsflag wird abgerufen, als ob durch std::fmtflags adjustfield = (flags & (std::ios_base::adjustfield)) und wie folgt untersucht, um die Auffüllposition zu ermitteln
- Wenn adjustfield == std::ios_base::left, wird danach aufgefüllt.
- Wenn adjustfield == std::ios_base::right, wird davor aufgefüllt.
- Wenn adjustfield == std::ios_base::internal und ein Vorzeichenzeichen in der Darstellung vorkommt, wird nach dem Vorzeichen aufgefüllt.
- Wenn adjustfield == std::ios_base::internal und die Darstellung in Schritt 1 mit 0x oder 0X begann, wird nach dem x oder X aufgefüllt.
- Andernfalls wird davor aufgefüllt.
- Wenn str.width() ungleich Null ist (z. B. wenn std::setw gerade verwendet wurde) und die Anzahl der
CharT's nach Schritt 2 kleiner als str.width() ist, dann werden Kopien des fill-Zeichens an der durch das Auffüllen angegebenen Position eingefügt, um die Länge der Sequenz auf str.width() zu bringen.
In jedem Fall wird str.width(0) aufgerufen, um die Auswirkungen von std::setw abzuschalten.
[bearbeiten] Schritt 4: Ausgabe
Jedes aufeinanderfolgende Zeichen c aus der Sequenz von CharT's aus Schritt 3 wird ausgegeben, als ob durch *out++ = c.
[bearbeiten] Parameter
| out | - | Iterator, der auf das erste zu überschreibende Zeichen zeigt |
| str | - | Stream, aus dem die Formatierungsinformationen abgerufen werden |
| fill | - | Füllzeichen, das verwendet wird, wenn das Ergebnis auf die Feldbreite aufgefüllt werden muss |
| val | - | Zu konvertierender und auszugebender Wert |
[bearbeiten] Rückgabewert
out
[bearbeiten] Hinweise
Die führende Null, die durch die Konvertierungsspezifikation #o erzeugt wird (z. B. als Ergebnis der Kombination von std::showbase und std::oct), wird nicht als Auffüllzeichen gezählt.
|
Beim Formatieren eines Fließkommawerts als Hexadezimalzahl (d. h. wenn floatfield == (std::ios_base::fixed | std::ios_base::scientific)) wird die Präzision des Streams nicht verwendet; stattdessen wird die Zahl immer mit ausreichender Präzision ausgegeben, um den Wert exakt darzustellen. |
(seit C++11) |
[bearbeiten] Beispiel
Eine Zahl mithilfe der Facette direkt ausgeben und eine benutzerdefinierte Facette demonstrieren
#include <iostream> #include <locale> // this custom num_put outputs squares of all integers (except long long) struct squaring_num_put : std::num_put<char> { iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long val) const { return std::num_put<char>::do_put(out, str, fill, val * val); } iter_type do_put(iter_type out, std::ios_base& str, char_type fill, unsigned long val) const { return std::num_put<char>::do_put(out, str, fill, val * val); } }; int main() { auto& facet = std::use_facet<std::num_put<char>>(std::locale()); facet.put(std::cout, std::cout, '0', 2.71); std::cout << '\n'; std::cout.imbue(std::locale(std::cout.getloc(), new squaring_num_put)); std::cout << 6 << ' ' << -12 << '\n'; }
Ausgabe
2.71 36 144
Eine Implementierung von operator<< für einen benutzerdefinierten Typ.
#include <iostream> #include <iterator> #include <locale> struct base { long x = 10; }; template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const base& b) { try { typename std::basic_ostream<CharT, Traits>::sentry s(os); if (s) { std::ostreambuf_iterator<CharT, Traits> it(os); std::use_facet<std::num_put<CharT>>(os.getloc()) .put(it, os, os.fill(), b.x); } } catch (...) { // set badbit on os and rethrow if required } return os; } int main() { base b; std::cout << b; }
Ausgabe
10
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 34 | C++98 | die bool-Überladung verwendete nicht existierende Member truename und falsename von std::ctype |
nutzen diese Member von std::numpunct |
| LWG 231 | C++98 | der Präzisionsmodifikator wurde nur hinzugefügt, wenn (flags & fixed) != 0 oder str.precision() > 0 |
diese Bedingungen wurden entfernt |
| LWG 282 | C++98 | die Tausendertrennzeichen wurden nur für Integral-Typen in Schritt 2 eingefügt |
auch eingefügt für Gleitkommatypen |
| LWG 4084 | C++11 | "NAN" und "INF" konnten nicht ausgegeben werden | sie können ausgegeben werden |
[bearbeiten] Siehe auch
| fügt formatierte Daten ein (public member function of std::basic_ostream<CharT,Traits>) |