std::num_get<CharT,InputIt>:: get, std::num_get<CharT,InputIt>:: do_get
| (1) | ||
|
public
:
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(seit C++11) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned short & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long long & v ) const ; |
(seit C++11) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, float & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
| (2) | ||
|
protected
:
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(seit C++11) | |
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned short & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std::
ios_base
::
iostate
&
err,
|
(seit C++11) | |
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, float & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
do_get
der abgeleitetesten Klasse auf.
Die Konvertierung erfolgt in drei Stufen:
Inhaltsverzeichnis |
Stufe 1: Auswahl des Konvertierungsspezifizierers
- I/O-Format-Flags werden abgerufen, als ob durch
- fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
- fmtflags boolalpha = ( str. flags ( ) & std:: ios_base :: boolalpha ) ;
- Wenn der Typ von v ein Ganzzahltyp ist, wird die erste zutreffende Wahl der folgenden fünf ausgewählt:
- Wenn basefield == oct , wird Konvertierungsspezifizierer % o verwendet
- Wenn basefield == hex , wird Konvertierungsspezifizierer % X verwendet
- Wenn basefield == 0 , wird Konvertierungsspezifizierer % i verwendet
- Wenn der Typ von v signiert ist, wird Konvertierungsspezifizierer % d verwendet
- Wenn der Typ von v unsigniert ist, wird Konvertierungsspezifizierer % u verwendet
- Für Ganzzahltypen wird bei Bedarf ein Längenmodifikator zur Konversionsspezifikation hinzugefügt: h für short und unsigned short , l für long und unsigned long , ll für long long und unsigned long long (seit C++11)
- Wenn der Typ von v float ist, wird die Konversionsspezifikation % g verwendet.
- Wenn der Typ von v double ist, wird die Konversionsspezifikation % lg verwendet.
- Wenn der Typ von v long double ist, wird die Konversionsspezifikation % Lg verwendet.
- Wenn der Typ von v void * ist, wird die Konversionsspezifikation % p verwendet.
- Wenn der Typ von v bool ist und boolalpha == 0 , wird verfahren, als ob der Typ von v long wäre, außer für den in Stufe 3 zu speichernden Wert in v .
-
Wenn der Typ von
v
bool
ist und
boolalpha
!
=
0
, ersetzen die folgenden Schritte die Stufen 2 und 3:
- Aufeinanderfolgende Zeichen vom Eingabeiterator in werden mit den Zeichensequenzen abgeglichen, die von std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) und std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) stammen, und zwar nur so weit wie nötig, um eine eindeutige Übereinstimmung zu identifizieren. Der Eingabeiterator in wird nur dann mit end verglichen, wenn ein Zeichen benötigt wird.
- Wenn die Zielsequenz eindeutig übereinstimmt, wird v auf den entsprechenden bool -Wert gesetzt. Andernfalls wird false in v gespeichert und std::ios_base::failbit wird err zugewiesen. Wenn vor Ende der Eingabe ( in == end ) keine eindeutige Übereinstimmung gefunden werden konnte, wird err | = std:: ios_base :: eofbit ausgeführt.
Stufe 2: Zeichenextraktion
- Wenn in == end , wird Phase 2 sofort beendet, keine weiteren Zeichen werden extrahiert.
-
Das nächste Zeichen wird aus
in
extrahiert, als ob durch
char_type ct
=
*
in
;
:
- Wenn das Zeichen mit einem der "0123456789abcdefxABCDEFX+-" (bis C++11) "0123456789abcdefpxABCDEFPX+-" (seit C++11) übereinstimmt, erweitert auf den char_type des Locales als ob durch std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( ) , wird es in das entsprechende char konvertiert.
- Wenn das Zeichen mit dem Dezimaltrennzeichen ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) ) ) übereinstimmt, wird es durch '.' ersetzt.
- Wenn das Zeichen mit dem Tausendertrennzeichen ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) ) übereinstimmt und die Tausendertrennung aktiv ist (bestimmt durch std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) . length ( ) ! = 0 ), dann wird, wenn der Dezimalpunkt '.' noch nicht akkumuliert wurde, die Position des Zeichens gemerkt, das Zeichen jedoch ansonsten ignoriert. Wenn der Dezimalpunkt bereits akkumuliert wurde, wird das Zeichen verworfen und Phase 2 beendet.
- In jedem Fall wird geprüft, ob das char aus den vorherigen Schritten im Eingabefeld erlaubt ist, das durch std::scanf geparst würde, gegeben den in Phase 1 ausgewählten Konvertierungsspezifizierer. Wenn es erlaubt ist, wird es in einem temporären Puffer akkumuliert und Phase 2 wiederholt sich. Wenn es nicht erlaubt ist, wird Phase 2 beendet.
Stufe 3: Konvertierung und Speicherung
- Die in Phase 2 akkumulierte Sequenz von char s wird in einen numerischen Wert umgewandelt:
|
(bis C++11) |
|
(seit C++11) |
- Wenn die Konvertierungsfunktion das gesamte Feld nicht konvertieren kann, wird der Wert 0 in v gespeichert.
- Wenn der Typ von v ein vorzeichenbehafteter Ganzzahltyp ist und die Konvertierungsfunktion einen positiven oder negativen Wert ergibt, der zu groß ist, um darin gespeichert zu werden, wird der größte positive bzw. negative darstellbare Wert in v gespeichert.
- Wenn der Typ von v ein vorzeichenloser Ganzzahltyp ist und die Konvertierungsfunktion einen Wert ergibt, der nicht hineinpasst, wird der größte positive darstellbare Wert in v gespeichert.
- In jedem Fall, wenn die Konvertierungsfunktion fehlschlägt, wird std::ios_base::failbit an err zugewiesen.
-
Andernfalls wird das numerische Ergebnis der Konvertierung in
v
gespeichert.
- Wenn der Typ von v bool ist und boolalpha nicht gesetzt ist, dann wird false gespeichert, wenn der zu speichernde Wert 0 ist, und true gespeichert, wenn der zu speichernde Wert 1 ist; für jeden anderen Wert wird std::ios_base::failbit an err zugewiesen und true gespeichert.
- Danach wird die Zifferngruppierung überprüft. Wenn die Position eines der in Phase 2 verworfenen Tausendertrennzeichen nicht mit der durch std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) bereitgestellten Gruppierung übereinstimmt, wird std::ios_base::failbit an err zugewiesen.
- Wenn Phase 2 durch den Test in == end beendet wurde, wird err | = std:: ios_base :: eofbit ausgeführt, um das EOF-Bit zu setzen.
Rückgabewert
in
Hinweise
Vor den Lösungen von LWG issue 23 und LWG issue 696 blieb v unverändert, falls ein Fehler auftritt.
Vor der Lösung von
LWG issue 221
wurden hexadezimale Ganzzahldarstellungen (z.B.
"0xA0"
) von
do_get(int)
zurückgewiesen, selbst wenn sie gültige Eingaben für
strtol
darstellten, da Stufe 2 die Zeichen
'X'
und
'x'
herausfilterte.
Vor der Lösung von LWG issue 1169 konnte die Konvertierung einer negativen Zahlzeichenkette in eine vorzeichenlose Ganzzahl Null ergeben (da der durch die Zeichenkette repräsentierte Wert kleiner ist als der, den der Zieltyp darstellen kann).
|
Vor der Lösung von
LWG Issue 2381
wurden hexadezimale Gleitkommazahlen mit Exponenten (z.B.
"0x1.23p-10"
) von
Zeichenketten, die Unendlich oder keine Zahl darstellen (z.B.
"NaN"
und
"inf"
), werden von
|
(seit C++11) |
Beispiel
Eine Implementierung von
operator>>
für einen benutzerdefinierten Typ.
#include <iostream> #include <iterator> #include <locale> struct base { long x; }; template<class CharT, class Traits> std::basic_istream<CharT, Traits>& operator >>(std::basic_istream<CharT, Traits>& is, base& b) { std::ios_base::iostate err = std::ios_base::goodbit; try // setting err could throw { typename std::basic_istream<CharT, Traits>::sentry s(is); if (s) // if stream is ready for input std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x); } catch (std::ios_base::failure& error) { // handle the exception } return is; } int main() { base b; std::cin >> b; }
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 17 | C++98 | der Prozess zum Parsen von Text-Booleschen Werten war fehlerhaft | korrigiert |
| LWG 18 | C++98 |
die Überladung von
get
mit
bool
&
Parameter fehlte
|
hinzugefügt |
| LWG 23 | C++98 | überlaufende Eingabe führte zu undefiniertem Verhalten | Überlauf behandelt |
| LWG 154 | C++98 | der Konvertierungsspezifizierer für double war % g (gleich wie für float ) | geändert zu % lg |
| LWG 221 | C++98 |
do_get
parse
'x'
und
'X'
nicht, während
strtol
sie parste
|
'x' und 'X' werden geparst |
| LWG 275 | C++98 |
get
hatte eine Überladung mit
short
&
anstelle von
float
&
|
korrigiert |
| LWG 358 | C++98 | Tausendertrennzeichen nach dem Dezimalpunkt wurden ignoriert | Phase 2 wird beendet, wenn sie auftreten |
| LWG 696 | C++98 | das Ergebnis blieb bei Konvertierungsfehlern unverändert | auf Null gesetzt |
| LWG 1169 | C++98 | Überlaufbehandlung war zwischen Gleitkommatypen inkonsistent |
konsistent gemacht
mit
strtof
/
strtod
|
| LWG 2381 | C++11 |
do_get
parse
'p'
und
'P'
nicht, während
strtod
sie parste
|
'p' und 'P' werden geparst |
Siehe auch
|
extrahiert formatierte Daten
(öffentliche Elementfunktion von
std::basic_istream<CharT,Traits>
)
|