Namensräume
Varianten
Aktionen

std::num_get<CharT,InputIt>:get, std::num_get<CharT,InputIt>:do_get

Von cppreference.com
< cpp‎ | locale‎ | num get
 
 
 
 
std::num_get
Memberfunktionen
num_get::getnum_get::do_get
 
(1)
public:

iter_type get( iter_type in, iter_type end, std::ios_base& str,

               std::ios_base::iostate& err, bool& v ) const;
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,

                          std::ios_base::iostate& err, bool& v ) const;
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,

                          unsigned 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, 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;
1) Öffentliche Memberfunktion, ruft die Memberfunktion do_get der am stärksten abgeleiteten Klasse auf.
2) Liest Zeichen aus dem Eingabeiterator in und generiert den Wert des Typs von v unter Berücksichtigung der I/O-Stream-Formatierungsflags von str.flags(), der Zeichenklassifizierungsregeln von std::use_facet<std::ctype<CharT>>(str.getloc()) und der numerischen Satzzeichen von std::use_facet<std::numpunct<CharT>>(str.getloc()). Diese Funktion wird von allen formatierten Eingabe-Stream-Operatoren wie std::cin >> n; aufgerufen.

Die Konvertierung erfolgt in drei Phasen

Inhalt

[bearbeiten] Phase 1: Auswahl des Konvertierungsspezifizierers

  • I/O-Formatflags werden wie folgt erhalten:
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 der Konvertierungsspezifizierer %o verwendet.
Wenn basefield = hex, wird der Konvertierungsspezifizierer %X verwendet.
Wenn basefield = 0, wird der Konvertierungsspezifizierer %i verwendet.
Wenn der Typ von v vorzeichenbehaftet ist, wird der Konvertierungsspezifizierer %d verwendet.
Wenn der Typ von v vorzeichenlos ist, wird der Konvertierungsspezifizierer %u verwendet.
  • Für Ganzzahltypen wird bei Bedarf ein Längenmodifikator zur Konvertierungsspezifikation 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 der Konvertierungsspezifizierer %g verwendet.
  • Wenn der Typ von v double ist, wird der Konvertierungsspezifizierer %lg verwendet.
  • Wenn der Typ von v long double ist, wird der Konvertierungsspezifizierer %Lg verwendet.
  • Wenn der Typ von v void* ist, wird der Konvertierungsspezifizierer %p verwendet.
  • Wenn der Typ von v bool ist und boolalpha = 0, verfährt man so, als ob der Typ von v long wäre, mit Ausnahme des Werts, der in Phase 3 in v gespeichert werden soll.
  • Wenn der Typ von v bool ist und boolalpha != 0, ersetzen die folgenden Phasen 2 und 3 dies:
    • Aufeinanderfolgende Zeichen, die aus dem Eingabeiterator in gelesen werden, werden mit den Zeichenfolgen abgeglichen, die von std::use_facet<std::numpunct<CharT>>(str.getloc()).falsename() und std::use_facet<std::numpunct<CharT>>(str.getloc()).truename() stammen, nur soweit notwendig, um die eindeutige Übereinstimmung zu identifizieren. Der Eingabeiterator in wird nur mit end verglichen, wenn dies zur Zeichenentnahme erforderlich ist.
    • 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 keine eindeutige Übereinstimmung gefunden werden konnte, bevor die Eingabe endete (in = end), wird err |= std::ios_base::eofbit ausgeführt.

[bearbeiten] Phase 2: Zeichenextraktion

  • Wenn in = end, wird Phase 2 sofort beendet, es werden keine weiteren Zeichen extrahiert.
  • Das nächste Zeichen wird aus in extrahiert, als ob durch char_type ct = *in;.
    • Wenn das Zeichen mit einem der folgenden Zeichen übereinstimmt, "0123456789abcdefxABCDEFX+-"(bis C++11)"0123456789abcdefpxABCDEFPX+-"(seit C++11), das gemäß der `char_type` der Locale wie durch std::use_facet<std::ctype<CharT>>(str.getloc()).widen() erweitert wird, wird es in das entsprechende char konvertiert.
    • Wenn das Zeichen mit dem Dezimaltrennzeichen übereinstimmt (std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point())), wird es durch '.' ersetzt.
    • Wenn das Zeichen mit dem Tausendertrennzeichen übereinstimmt (std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep()) 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 angesammelt wurde, die Position des Zeichens gespeichert, das Zeichen wird aber ansonsten ignoriert. Wenn der Dezimalpunkt bereits angesammelt wurde, wird das Zeichen verworfen und Phase 2 beendet.
    • In jedem Fall wird geprüft, ob das in den vorherigen Schritten ermittelte char im Eingabefeld zulässig ist, das von std::scanf mit dem in Phase 1 ausgewählten Konvertierungsspezifizierer geparst würde. Wenn es zulässig ist, wird es in einem temporären Puffer angesammelt und Phase 2 wiederholt. Wenn es nicht zulässig ist, wird Phase 2 beendet.

[bearbeiten] Phase 3: Konvertierung und Speicherung

  • Die in Phase 2 angesammelte Sequenz von chars wird in einen numerischen Wert konvertiert.
Die Eingabe wird gemäß den Regeln von std::scanf geparst.
(bis C++11)
Die Eingabe wird wie folgt geparst:
(seit C++11)
  • Wenn die Konvertierungsfunktion das gesamte Feld nicht erfolgreich 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 hineinzupassen, wird der am positivsten oder negativsten 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 am positivsten darstellbare Wert in v gespeichert.
  • In jedem Fall wird, wenn die Konvertierungsfunktion fehlschlägt, std::ios_base::failbit 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, wenn der zu speichernde Wert 0 ist, false gespeichert, wenn der zu speichernde Wert 1 ist, wird true gespeichert. Bei jedem anderen Wert wird std::ios_base::failbit err zugewiesen und true gespeichert.
  • Danach wird die Zifferngruppierung überprüft. Wenn die Position eines der in Phase 2 verworfenen Tausendertrennzeichen nicht mit der Gruppierung durch std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping() nicht übereinstimmt, wird std::ios_base::failbit 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.

[bearbeiten] Rückgabewert

in

[bearbeiten] Hinweise

Vor der Lösung der Probleme LWG issue 23 und LWG issue 696 wurde v bei einem Fehler unverändert gelassen.

Vor der Lösung von LWG issue 221 wurden Zeichenketten, die hexadezimale Ganzzahlen darstellen (z. B. "0xA0"), von do_get(int) abgelehnt, auch wenn sie gültige Eingaben für strtol sind, da Phase 2 die Zeichen 'X' und 'x' filtert.

Vor der Lösung von LWG issue 1169 konnte die Konvertierung einer negativen Zahlzeichenkette in eine vorzeichenlose Ganzzahl Null ergeben (da der von der Zeichenkette dargestellte Wert kleiner ist als das, was der Zieltyp darstellen kann).

Vor der Lösung von LWG issue 2381 wurden Zeichenketten, die hexadezimale Gleitkommazahlen mit Exponenten darstellen (z. B. "0x1.23p-10"), von do_get(double) abgelehnt, auch wenn sie gültige Eingaben für strtod sind, da Phase 2 die Zeichen 'P' und 'p' filtert.

Die Zeichenketten, die Unendlichkeit oder "keine Zahl" darstellen (z. B. "NaN" und "inf"), werden von do_get(double) abgelehnt, auch wenn sie gültige Eingaben für strtod sind, da Phase 2 Zeichen wie 'N' oder 'i' filtert.

(seit C++11)

[bearbeiten] 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;
}

[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 17 C++98 Der Prozess des Parsens von Text-Boolean-Werten war fehlerhaft korrigiert
LWG 18 C++98 Die Überladung von get, die einen bool&-Wert nimmt, fehlte hinzugefügt
LWG 23 C++98 Überlaufende Eingaben führten zu undefiniertem Verhalten Überlauf behandelt
LWG 154 C++98 Der Konvertierungsspezifizierer für double war %g (wie für float) Geändert zu %lg
LWG 221 C++98 do_get parste 'x' und 'X' nicht, während strtol sie parste 'x' und 'X' wurden geparst
LWG 275 C++98 get hatte eine Überladung, die einen short&-Wert anstelle eines float&-Werts nahm korrigiert
LWG 358 C++98 Tausendertrennzeichen nach dem Dezimalpunkt wurden ignoriert Phase 2 wird beendet, wenn sie angetroffen werden
LWG 696 C++98 Das Ergebnis blieb bei Konvertierungsfehlern unverändert Auf Null gesetzt
LWG 1169 C++98 Die Überlaufbehandlung war bei Gleitkommatypen inkonsistent konsistent gemacht
mit strtof/strtod
LWG 2381 C++11 do_get parste 'p' und 'P' nicht, während strtod sie parste 'p' und 'P' wurden geparst

[bearbeiten] Siehe auch

extrahiert formatierte Daten
(public member function of std::basic_istream<CharT,Traits>) [edit]