Namespaces
Variants

std::scanf, std::fscanf, std::sscanf

Von de.cppreference.net
< cpp | io | c
 
 
 
C-artige I/O
Typen und Objekte
Funktionen
Dateizugriff
Direkte Eingabe/Ausgabe
Unformatierte Eingabe/Ausgabe
Formatierte Eingabe
(C++11)(C++11)(C++11)    
(C++11)(C++11)(C++11)    
 
Definiert in Header <cstdio>
int scanf( const char* format, ... );
(1)
int fscanf( std::FILE* stream, const char* format, ... );
(2)
int sscanf( const char* buffer, const char* format, ... );
(3)

Liest Daten aus verschiedenen Quellen, interpretiert sie gemäß format und speichert die Ergebnisse in die angegebenen Speicherorte.

1) Liest die Daten von stdin.
2) Liest die Daten aus dem Dateistrom stream.
3) Liest die Daten aus der nullterminierten Zeichenkette buffer.

Parameter

stream - Eingabedateistrom zum Lesen
buffer - Zeiger auf eine nullterminierte Zeichenkette zum Lesen
format - Zeiger auf eine nullterminierte Zeichenkette, die angibt, wie die Eingabe gelesen werden soll
... - Empfangsargumente

Die format-Zeichenkette besteht aus

  • Nicht-Leerzeichen-Multibyte-Zeichen außer %: jedes solche Zeichen in der Formatzeichenkette verbraucht genau ein identisches Zeichen aus dem Eingabestrom oder verursacht einen Fehler der Funktion, falls das nächste Zeichen im Strom nicht gleich ist.
  • Leerzeichen: jedes einzelne Leerzeichen in der Formatzeichenkette verbraucht alle verfügbaren aufeinanderfolgenden Leerzeichen aus der Eingabe (ermittelt, als ob std::isspace in einer Schleife aufgerufen würde). Beachten Sie, dass es keinen Unterschied zwischen "\n", " ", "\t\t" oder anderen Leerzeichen in der Formatzeichenkette gibt.
  • Konvertierungsspezifikationen. Jede Konvertierungsspezifikation hat das folgende Format:
  • Einführendes %-Zeichen.
  • (optional) Zuweisungsunterdrückungszeichen *. Wenn diese Option vorhanden ist, weist die Funktion das Ergebnis der Konvertierung keinem Empfangsargument zu.
  • (optional) Ganzzahl (größer als Null), die die maximale Feldbreite angibt, d. h. die maximale Anzahl von Zeichen, die die Funktion bei der Konvertierung gemäß der aktuellen Konvertierungsspezifikation verbrauchen darf. Beachten Sie, dass %s und %[ zu einem Pufferüberlauf führen können, wenn die Breite nicht angegeben wird.
  • (optional) Längenmodifikator, der die Größe des Empfangsarguments angibt, d. h. den tatsächlichen Zieltyp. Dies beeinflusst die Konvertierungsgenauigkeit und Überlaufregeln. Der Standard-Zieltyp ist für jeden Konvertierungstyp unterschiedlich (siehe Tabelle unten).
  • Konvertierungsformatspezifizierer.

Die folgenden Formatspezifizierer sind verfügbar:

Konvertierung
spezifizierer
Erläuterung Erwarteter
Argumenttyp
Längenmodifikator→ hh h kein l ll j z t L
Nur seit C++11 verfügbar→ Ja Ja Ja Ja Ja
%
Entspricht dem Literal %.
N/V N/V N/V N/V N/V N/V N/V N/V N/V
c

Entspricht einem Zeichen oder einer Folge von Zeichen.

  • Wenn ein Breitenspezifizierer verwendet wird, werden genau width Zeichen gematcht (das Argument muss ein Zeiger auf ein Array mit ausreichend Platz sein).
  • Im Gegensatz zu %s und %[ wird der Nullterminator nicht an das Array angehängt.
N/V N/V
char*
wchar_t*
N/V N/V N/V N/V N/V
s

Entspricht einer Folge von Nicht-Leerzeichen (einer Zeichenkette).

  • Wenn ein Breitenspezifizierer verwendet wird, werden bis zu width oder bis zum ersten Leerzeichen gematcht, je nachdem, was zuerst auftritt.
  • Speichert immer ein Nullzeichen zusätzlich zu den gematchten Zeichen (daher muss das Argument-Array Platz für mindestens width+1 Zeichen haben).
[set ]

Entspricht einer nicht-leeren Folge von Zeichen aus der set von Zeichen.

  • Wenn das erste Zeichen der Menge ^ ist, werden alle Zeichen gematcht, die nicht in der Menge sind.
  • Wenn die Menge mit ] oder ^] beginnt, wird das Zeichen ] ebenfalls in die Menge aufgenommen.
  • Es ist implementierungsabhängig, ob das Zeichen - an nicht-anfänglicher Position im Scanset einen Bereich anzeigen kann, wie in [0-9].
  • Wenn ein Breitenspezifizierer verwendet wird, werden nur bis zu width gematcht.
  • Speichert immer ein Nullzeichen zusätzlich zu den gematchten Zeichen (daher muss das Argument-Array Platz für mindestens width+1 Zeichen haben).
d

Entspricht einer Dezimalzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtol mit dem Wert 10 für das base-Argument erwartet.
signed char* oder unsigned char*
signed short* oder unsigned short*
signed int* oder unsigned int*
signed long* oder unsigned long*
signed long long* oder unsigned long long*
std::intmax_t* oder std::uintmax_t*
std::size_t*
std::ptrdiff_t*
N/V
b (C++26)

Entspricht einer vorzeichenlosen Binärzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtoul mit dem Wert 2 für das base-Argument erwartet.
i

Entspricht einer Ganzzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtol mit dem Wert 0 für das base-Argument erwartet (Basis wird durch die ersten geparsten Zeichen bestimmt).
u

Entspricht einer vorzeichenlosen Dezimalzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtoul mit dem Wert 10 für das base-Argument erwartet.
o

Entspricht einer vorzeichenlosen Oktalzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtoul mit dem Wert 8 für das base-Argument erwartet.
x
X

Entspricht einer vorzeichenlosen Hexadezimalzahl.

  • Das Format der Zahl ist dasselbe wie von std::strtoul mit dem Wert 16 für das base-Argument erwartet.
n

Gibt die Anzahl der bisher gelesenen Zeichen zurück.

  • Es werden keine Eingaben verbraucht. Erhöht nicht die Zuweisungsanzahl.
  • Wenn der Spezifizierer einen Zuweisungsunterdrückungsoperator definiert hat, ist das Verhalten undefiniert.
a (C++11)
A (C++11)
e
E
f
F (C++11)
g
G

Entspricht einer Gleitkommazahl.

  • Das Format der Zahl ist dasselbe wie von std::strtof erwartet.
N/V N/V
float*
double*
N/V N/V N/V N/V
long double*
p

Entspricht einer implementierungsdefinierten Zeichenfolge, die einen Zeiger definiert.

  • printf-Familie von Funktionen sollte dieselbe Sequenz mit dem %p-Formatspezifizierer erzeugen.
N/V N/V
void**
N/V N/V N/V N/V N/V N/V
Hinweise

Für jeden Konvertierungsspezifizierer außer n wird die längste Sequenz von Eingabezeichen, die keine angegebene Feldbreite überschreitet und entweder genau das ist, was der Konvertierungsspezifizierer erwartet, oder ein Präfix einer solchen Sequenz ist, vom Strom verbraucht. Das erste Zeichen, falls vorhanden, nach dieser verbrauchten Sequenz bleibt ungelesen. Wenn die verbrauchte Sequenz die Länge Null hat oder nicht wie oben angegeben konvertiert werden kann, tritt ein Matching-Fehler auf, es sei denn, Dateiende, ein Kodierungsfehler oder ein Lesefehler verhinderte die Eingabe vom Strom; in diesem Fall liegt ein Eingabefehler vor.

Außer beim %-Spezifizierer wird das Eingabeelement (oder bei %n die Anzahl der Eingabezeichen) zunächst in einen zum Konvertierungsspezifizierer passenden Typ konvertiert. Sofern die Zuweisung nicht mit * unterdrückt wurde, wird das Ergebnis der Konvertierung in das Objekt geschrieben, auf das das nächste noch nicht beschriebene Argument zeigt. Wenn dieses Objekt keinen passenden Typ hat oder das Ergebnis der Konvertierung nicht im Objekt dargestellt werden kann, ist das Verhalten undefiniert.

Alle Konvertierungsspezifizierer außer [, c und n verbrauchen und verwerfen alle führenden Leerzeichen (ermittelt, als ob std::isspace aufgerufen würde), bevor sie versuchen, die Eingabe zu parsen. Diese verbrauchten Zeichen zählen nicht zur angegebenen maximalen Feldbreite.

Die Konvertierungsspezifizierer lc, ls und l[ führen eine Multibyte-zu-Breitzeichen-Konvertierung durch, als ob std::mbrtowc mit einem std::mbstate_t-Objekt aufgerufen würde, das vor der Konvertierung des ersten Zeichens auf Null initialisiert wird.

Die Konvertierungsspezifizierer s und [ speichern immer den Nullterminator zusätzlich zu den gematchten Zeichen. Die Größe des Ziel-Arrays muss mindestens eins größer sein als die angegebene Feldbreite. Die Verwendung von %s oder %[ ohne Angabe der Ziel-Array-Größe ist genauso unsicher wie std::gets.

Die korrekten Konvertierungsspezifikationen für die Ganzzahltypen mit fester Breite (std::int8_t, usw.) sind im Header <cinttypes> definiert (obwohl SCNdMAX, SCNuMAX, usw. synonym zu %jd, %ju, usw. sind).

Es gibt einen Sequenzpunkt nach der Aktion jedes Konvertierungsspezifizierers; dies erlaubt das Speichern mehrerer Felder in derselben „Senken“-Variablen.

Beim Parsen eines unvollständigen Gleitkommawerts, der im Exponenten ohne Ziffern endet, wie z. B. das Parsen von "100er" mit dem Konvertierungsspezifizierer %f, wird die Sequenz "100e" (das längste Präfix einer möglicherweise gültigen Gleitkommazahl) verbraucht, was zu einem Matching-Fehler führt (die verbrauchte Sequenz kann nicht in eine Gleitkommazahl konvertiert werden), wobei "r" übrig bleibt. Einige vorhandene Implementierungen befolgen diese Regel nicht und rollen zurück, um nur "100" zu verbrauchen, wobei "er" übrig bleibt, z. B. glibc Bug 1765.

Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten undefiniert.

Rückgabewert

Anzahl der erfolgreich zugewiesenen Empfangsargumente (kann Null sein, falls ein Matching-Fehler vor der Zuweisung des ersten Empfangsarguments auftrat), oder EOF, falls ein Eingabefehler vor der Zuweisung des ersten Empfangsarguments auftritt.

Komplexität

Nicht garantiert. Insbesondere sind einige Implementierungen von std::sscanf O(N), wobei N = std::strlen(buffer) [1]. Für leistungsstarkes String-Parsing siehe std::from_chars.

Hinweise

Da die meisten Konvertierungsspezifizierer zunächst alle aufeinanderfolgenden Leerzeichen verbrauchen, wird Code wie

std::scanf("%d", &a);
std::scanf("%d", &b);

zwei Ganzzahlen einlesen, die in verschiedenen Zeilen eingegeben werden (der zweite %d verbraucht den von der ersten übriggelassenen Zeilenumbruch) oder in derselben Zeile, getrennt durch Leerzeichen oder Tabulatoren (der zweite %d verbraucht die Leerzeichen oder Tabulatoren).

Die Konvertierungsspezifizierer, die keine führenden Leerzeichen verbrauchen, wie %c, können dazu gebracht werden, indem ein Leerzeichen in der Formatzeichenkette verwendet wird:

std::scanf("%d", &a);
std::scanf(" %c", &c); // ignore the endline after %d, then read a char

Beachten Sie, dass einige Implementierungen von std::sscanf einen Aufruf von std::strlen beinhalten, was ihre Laufzeit linear zur Länge der gesamten Zeichenkette macht. Dies bedeutet, dass wenn std::sscanf in einer Schleife aufgerufen wird, um wiederholt Werte vom Anfang einer Zeichenkette zu parsen, Ihr Code möglicherweise in quadratischer Zeit läuft (Beispiel).

Beispiel

#include <clocale>
#include <cstdio>
#include <iostream>

int main()
{
    int i, j;
    float x, y;
    char str1[10], str2[4];
    wchar_t warr[2];
    std::setlocale(LC_ALL, "en_US.utf8");

    char input[] = "25 54.32E-1 Thompson 56789 0123 56ß水";
    // parse as follows:
    // %d: an integer 
    // %f: a floating-point value
    // %9s: a string of at most 9 non-whitespace characters
    // %2d: two-digit integer (digits 5 and 6)
    // %f: a floating-point value (digits 7, 8, 9)
    // %*d an integer which isn't stored anywhere
    // ' ': all consecutive whitespace
    // %3[0-9]: a string of at most 3 digits (digits 5 and 6)
    // %2lc: two wide characters, using multibyte to wide conversion
    const int ret = std::sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
                                &i, &x, str1, &j, &y, str2, warr);

    std::cout << "Converted " << ret << " fields:\n"
                 "i = " << i << "\n"
                 "x = " << x << "\n"
                 "str1 = " << str1 << "\n"
                 "j = " << j << "\n"
                 "y = " << y << "\n"
                 "str2 = " << str2 << std::hex << "\n"
                 "warr[0] = U+" << (int)warr[0] << "\n"
                 "warr[1] = U+" << (int)warr[1] << '\n';
}

Ausgabe:

Converted 7 fields:
i = 25
x = 5.432
str1 = Thompson
j = 56
y = 789
str2 = 56
warr[0] = U+df
warr[1] = U+6c34

Siehe auch

(C++11)(C++11)(C++11)
liest formatierte Eingabe von stdin, einem Dateistrom oder einem Puffer
unter Verwendung einer variablen Argumentliste
(Funktion)
holt eine Zeichenkette aus einem Dateistrom
(Funktion)
gibt formatierte Ausgabe an stdout, einen Dateistrom oder einen Puffer aus
(Funktion)
konvertiert eine Zeichenfolge in einen Ganzzahl- oder Gleitkommawert
(Funktion)
C-Dokumentation für scanf, fscanf, sscanf