Namensräume
Varianten
Aktionen

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

Von cppreference.com
< cpp‎ | io‎ | c
 
 
 
C-Style I/O
Typen und Objekte
Funktionen
Datei-Zugriff
Direkte Ein-/Ausgabe
Unformatierte Ein-/Ausgabe
Formatierte Eingabe
scanffscanfsscanf
(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 an den angegebenen Speicherorten.

1) Liest die Daten von stdin.
2) Liest die Daten aus dem Dateistream stream.
3) Liest die Daten aus dem nullterminierten Zeichenstring buffer.

Inhalt

[bearbeiten] Parameter

stream - Eingabedateistream, aus dem gelesen werden soll.
buffer - Zeiger auf einen nullterminierten Zeichenstring, aus dem gelesen werden soll
format - Zeiger auf einen nullterminierten Zeichenstring, der angibt, wie die Eingabe gelesen werden soll
... - Empfangende Argumente

Der Formatstring besteht aus

  • Nicht-Whitespace-Multibyte-Zeichen außer %: Jedes solche Zeichen in der Formatzeichenkette verbraucht genau ein identisches Zeichen aus dem Eingabestrom oder führt zum Fehlschlag der Funktion, wenn das nächste Zeichen im Strom nicht übereinstimmt.
  • Whitespace-Zeichen: Jedes einzelne Whitespace-Zeichen in der Formatzeichenkette verbraucht alle verfügbaren aufeinanderfolgenden Whitespace-Zeichen aus der Eingabe (bestimmt, als ob std::isspace in einer Schleife aufgerufen worden wäre). Beachten Sie, dass es keinen Unterschied zwischen "\n", " ", "\t\t" oder anderem Whitespace in der Formatzeichenkette gibt.
  • Konvertierungsspezifikationen. Jede Konvertierungsspezifikation hat das folgende Format:
  • Einführendes %-Zeichen.
  • (optional) Zuweisungsunterdrückendes Zeichen *. Wenn diese Option vorhanden ist, weist die Funktion das Ergebnis der Konvertierung keinem empfangenden Argument zu.
  • (optional) Ganze Zahl (größer als Null), die die *maximale Feldbreite* angibt, d. h. die maximale Anzahl von Zeichen, die die Funktion bei der durch die aktuelle Konvertierungsspezifikation angegebenen Konvertierung verbrauchen darf. Beachten Sie, dass %s und %[ zu einem Pufferüberlauf führen können, wenn die Breite nicht angegeben ist.
  • (optional) Längenmodifikator, der die Größe des Empfängerarguments angibt, d.h. den tatsächlichen Zieltyp. Dies wirkt sich auf die Genauigkeit der Konvertierung und die Überlaufregeln aus. Der Standard-Zieltyp ist für jeden Konvertierungstyp unterschiedlich (siehe Tabelle unten).
  • Ein Konversionsformat-Spezifizierer.

Die folgenden Format-Spezifizierer sind verfügbar:

Konversion
Spezifizierer
Erklärung Erwartet
Argumenttyp
Längenmodifikator → hh h keine l ll j z t L
Nur verfügbar ab C++11 → Ja Ja Ja Ja Ja
%
Entspricht dem literalen %.
N/A N/A N/A N/A N/A N/A N/A N/A N/A
c

Entspricht einem Zeichen oder einer Sequenz von Zeichen.

  • Wenn ein Breitenangabe verwendet wird, werden genau Breite Zeichen abgeglichen (das Argument muss ein Zeiger auf ein Array mit ausreichend Platz sein).
  • Im Gegensatz zu %s und %[ wird kein Nullzeichen an das Array angehängt.
N/A N/A
char*
wchar_t*
N/A N/A N/A N/A N/A
s

Entspricht einer Sequenz von Nicht-Whitespace-Zeichen (einem String).

  • Wenn ein Breiten-Spezifizierer verwendet wird, werden bis zu Breite oder bis zum ersten Whitespace-Zeichen abgeglichen, je nachdem, was zuerst eintritt.
  • Speichert immer ein Nullzeichen zusätzlich zu den abgeglichenen Zeichen (daher muss das Argumentarray Platz für mindestens Breite+1 Zeichen haben).
[set ]

Entspricht einer nicht-leeren Sequenz von Zeichen aus set von Zeichen.

  • Wenn das erste Zeichen des Sets ^ ist, werden alle Zeichen, die nicht im Set enthalten sind, abgeglichen.
  • Wenn das Set mit ] oder ^] beginnt, wird das Zeichen ] ebenfalls in das Set aufgenommen.
  • Es ist implementierungsabhängig, ob das Zeichen - in nicht-initialer Position im Scanset einen Bereich angibt, wie in [0-9].
  • Wenn ein Breiten-Spezifizierer verwendet wird, werden nur bis zu Breite abgeglichen.
  • Speichert immer ein Nullzeichen zusätzlich zu den abgeglichenen Zeichen (daher muss das Argumentarray Platz für mindestens Breite+1 Zeichen haben).
d

Entspricht einer Dezimalganzzahl.

  • Das Format der Zahl ist dasselbe, wie es von std::strtol mit dem Wert 10 für das Argument base erwartet wird.
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*
N/A
i

Entspricht einer Ganzzahl.

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

Entspricht einer vorzeichenlosen Dezimalganzzahl.

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

Entspricht einer vorzeichenlosen Oktalganzzahl.

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

Entspricht einer vorzeichenlosen Hexadezimalganzzahl.

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

Gibt die bisher gelesene Anzahl von Zeichen zurück.

  • Es werden keine Eingaben verbraucht. Erhöht die Zählung der Zuweisungen nicht.
  • Wenn der Spezifizierer den Operator zur Unterdrückung von Zuweisungen aufweist, 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 es von std::strtof erwartet wird.
N/A N/A
float*
double*
N/A N/A N/A N/A
long double*
p

Entspricht einer implementierungsdefinierten Zeichensequenz, die einen Zeiger definiert.

  • Die `printf`-Funktionsfamilie sollte mit dem Format-Spezifizierer `%p` die gleiche Sequenz erzeugen.
N/A N/A
void**
N/A N/A N/A N/A N/A N/A
Anmerkungen

Für jeden Konvertierungsspezifizierer außer n gilt: Die längste Folge von Eingabezeichen, die keine angegebene Feldbreite überschreitet und entweder genau dem entspricht, was der Konvertierungsspezifizierer erwartet, oder ein Präfix einer Folge ist, die er erwarten würde, wird aus dem Strom verbraucht. Das erste Zeichen nach dieser verbrauchten Folge bleibt ungelesen. Wenn die verbrauchte Folge eine Länge von Null hat oder wenn die verbrauchte Folge nicht wie oben angegeben konvertiert werden kann, tritt ein Abgleichfehler auf, es sei denn, EOF, ein Kodierungsfehler oder ein Lesefehler hat die Eingabe aus dem Strom verhindert, in welchem Fall es sich um einen Eingabefehler handelt.

Alle Konvertierungsspezifizierer außer [, c und n verbrauchen und verwerfen alle führenden Whitespace-Zeichen (bestimmt, als ob std::isspace aufgerufen worden wäre), bevor versucht wird, 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-Wide-Character-Konvertierung durch, als ob std::mbrtowc mit einem std::mbstate_t-Objekt auf Null initialisiert worden wäre, bevor das erste Zeichen konvertiert wurde.

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

Die korrekten Konvertierungsspezifizierer für die Integer-Typen fester Breite (std::int8_t, etc.) sind im Header <cinttypes> definiert (obwohl SCNdMAX, SCNuMAX, etc. synonym mit %jd, %ju, etc. sind).

Nach der Aktion jedes Konvertierungsspezifizierers gibt es einen Sequenzpunkt; dies ermöglicht die Speicherung mehrerer Felder in derselben "Senken"-Variable.

Beim Parsen eines unvollständigen Fließkommawerts, der mit dem Exponenten ohne Ziffern endet, z. B. beim Parsen von "100er" mit dem Konvertierungsspezifizierer %f, wird die Sequenz "100e" (das längste Präfix einer möglicherweise gültigen Fließkommazahl) verbraucht, was zu einem Abgleichfehler führt (die verbrauchte Folge kann nicht in eine Fließkommazahl konvertiert werden), wobei "r" übrig bleibt. Einige bestehende Implementierungen folgen dieser Regel nicht und rollen zurück, um nur "100" zu verbrauchen, wodurch "er" übrig bleibt, z. B. glibc-Bug 1765.

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

[bearbeiten] Rückgabewert

Anzahl der erfolgreich zugewiesenen empfangenden Argumente (die Null sein kann, falls ein Abgleichfehler auftrat, bevor das erste empfangende Argument zugewiesen wurde), oder EOF, wenn ein Eingabefehler auftritt, bevor das erste empfangende Argument zugewiesen wurde.

[bearbeiten] Komplexität

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

[bearbeiten] Anmerkungen

Da die meisten Konvertierungsspezifizierer zuerst alle aufeinanderfolgenden Whitespaces verbrauchen, liest Code wie

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

zwei ganze Zahlen ein, die auf unterschiedlichen Zeilen eingegeben werden (die zweite %d verbraucht den von der ersten übrig gelassenen Zeilenumbruch) oder auf derselben Zeile, getrennt durch Leerzeichen oder Tabs (die zweite %d verbraucht die Leerzeichen oder Tabs).

Die Konvertierungsspezifizierer, die keine führenden Whitespaces verbrauchen, wie z. B. %c, können dazu veranlasst werden, dies zu tun, indem ein Whitespace-Zeichen 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 des gesamten Strings macht. Das bedeutet, wenn std::sscanf in einer Schleife aufgerufen wird, um wiederholt Werte vom Anfang eines Strings zu parsen, kann Ihr Code quadratische Zeit benötigen (Beispiel).

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

[bearbeiten] Siehe auch

(C++11)(C++11)(C++11)
liest formatierte Eingaben von stdin, einem Dateistream oder einem Puffer
mit variabler Argumentenliste
(function) [bearbeiten]
liest einen Zeichenstring aus einem Dateistream
(function) [bearbeiten]
druckt formatierte Ausgabe nach stdout, einen Dateistream oder einen Puffer
(Funktion) [bearbeiten]
konvertiert eine Zeichensequenz in einen Ganzzahl- oder Gleitkommawert
(Funktion) [bearbeiten]
C-Dokumentation für scanf, fscanf, sscanf