scanf format string - scanf format string

A Scanf Formatzeichenkette ( scan f ormatted) ist ein Steuerparameter in verschiedenen verwendeten Funktionen , um das Layout eines Eingangs angeben Zeichenfolge . Die Funktionen können dann die Zeichenfolge teilen und in Werte geeigneter Datentypen übersetzen . Funktionen zum Scannen von Zeichenfolgen werden häufig in Standardbibliotheken bereitgestellt .

Der Begriff "scanf" stammt aus der C-Bibliothek , die diese Art von Funktion populär gemacht hat, aber solche Funktionen sind älter als C, und andere Namen werden verwendet, wie beispielsweise readf in ALGOL 68 . Scanf Formatzeichenfolgen, die eingegeben formatiert Bereitstellung ( Parsing ), sind komplementär zu printf Formatzeichenfolgen , die formatierte Ausgabe bereitzustellen ( Templat ). Diese bieten einfache Funktionen und ein festes Format im Vergleich zu anspruchsvolleren und flexibleren Parsern oder Template-Engines, sind jedoch für viele Zwecke ausreichend.

Geschichte

Mike Lesk ‚s tragbare Eingabe / Ausgabe - Bibliothek , einschließlich scanf , wurde offiziell Teil von Unix in der Version 7 .

Verwendung

Die scanf Funktion, die in C enthalten ist , liest Eingaben für Zahlen und andere Datentypen aus der Standardeingabe (häufig eine Befehlszeilenschnittstelle oder eine ähnliche Art von Textbenutzeroberfläche ).

Der folgende C - Code liest eine variable Anzahl von unformatiert dezimal Zahlen aus dem Standardeingabestrom und druckt jede von ihnen aus auf separaten Zeilen:

#include <stdio.h>

int main(void)
{
    int n;

    while (scanf("%d", &n) == 1)
        printf("%d\n", n);
    return 0;
}

Nach der Verarbeitung durch das obige Programm wird eine unregelmäßig verteilte Liste von Ganzzahlen wie z

456 123 789 456 12
456 1
      2378

wird in konsistenten Abständen angezeigt als:

456
123
789
456
12
456
1
2378

So drucken Sie ein Wort aus:

#include <stdio.h>

int main(void)
{
    char word[20];

    if (scanf("%19s", word) == 1)
        puts(word);
    return 0;
}

Unabhängig vom Datentyp, den der Programmierer vom Programm lesen lassen möchte, müssen die Argumente (wie &n oben) Zeiger sein, die auf den Speicher zeigen. Andernfalls wird die Funktion nicht korrekt ausgeführt, da versucht wird, die falschen Speicherbereiche zu überschreiben, anstatt auf den Speicherort der Variablen zu zeigen, für die Sie eine Eingabe erhalten möchten.

Im letzten Beispiel wird ein address-of-Operator ( & ) nicht für das Argument verwendet: Wie word der Name eines Arrays von char , so ist es (in allen Kontexten, in denen es zu einer Adresse ausgewertet wird) einem Zeiger auf das erste Element des Arrays. Während der Ausdruck &word semantisch numerisch mit demselben Wert ausgewertet wird, hat er eine völlig andere Bedeutung, da er eher für die Adresse des gesamten Arrays als für ein Element davon steht. Diese Tatsache muss bei der Zuweisung der scanf Ausgabe zu Zeichenfolgen berücksichtigt werden .

Wie scanf nur zum Lesen von Standardeingaben vorgesehen ist , weisen viele Programmiersprachen mit Schnittstellen wie PHP Ableitungen wie sscanf und fscanf aber nicht scanf selbst auf.

Formatieren Sie die Zeichenfolgenspezifikationen

Die Formatierungs Platzhalter in scanf mehr oder weniger das gleiche wie das in printf seiner umgekehrten Funktion. Wie in printf ist die POSIX-Erweiterung n$ definiert.

Es gibt selten Konstanten (dh Zeichen, die keine Platzhalter formatieren ) in einer Formatzeichenfolge, hauptsächlich weil ein Programm normalerweise nicht zum Lesen bekannter Daten ausgelegt ist scanf , diese jedoch akzeptiert, wenn dies explizit angegeben wird. Die Ausnahme sind ein oder mehrere Leerzeichen , wodurch alle Leerzeichen in der Eingabe verworfen werden.

Einige der am häufigsten verwendeten Platzhalter folgen:

  • %a  : Scannen Sie eine Gleitkommazahl in hexadezimaler Schreibweise.
  • %d  : Scannen Sie eine Ganzzahl als vorzeichenbehaftete Dezimalzahl .
  • %i  : Scannen Sie eine Ganzzahl als vorzeichenbehaftete Zahl. Ähnlich %d , interpretiert die Zahl jedoch als hexadezimal, wenn sie vorangestellt wird, 0x und als oktal, wenn sie vorangestellt wird 0 . Zum Beispiel 031 würde die Zeichenfolge als 31 using %d und 25 using gelesen %i . Das Flag h in %hi zeigt die Konvertierung in a short und die hh Konvertierung in a an char .
  • %u  : Nach Dezimalstellen suchen unsigned int (Beachten Sie, dass im C99-Standard das Minuszeichen für den Eingabewert optional ist. Wenn also ein Minuszeichen gelesen wird, treten keine Fehler auf und das Ergebnis ist das Zweierkomplement einer negativen Zahl, wahrscheinlich ein sehr großer Wert. Siehe strtoul() .) %hu Scannt entsprechend nach einem unsigned short und %hhu nach einem unsigned char .
  • %f  : Scannen Sie eine Gleitkommazahl in normaler ( Festkomma- ) Notation.
  • %g , %G  : Scannen Sie eine Gleitkommazahl in normaler oder exponentieller Notation. %g verwendet Kleinbuchstaben und %G Großbuchstaben.
  • %x , %X  : Scannen Sie eine Ganzzahl als vorzeichenlose Hexadezimalzahl .
  • %o  : Scannen Sie eine Ganzzahl als Oktalzahl .
  • %s  : Eine Zeichenfolge scannen . Der Scan wird mit Leerzeichen beendet . Am Ende der Zeichenfolge wird ein Nullzeichen gespeichert. Dies bedeutet, dass der bereitgestellte Puffer mindestens ein Zeichen länger als die angegebene Eingabelänge sein muss.
  • %c  : Scanne ein Zeichen (char). Es wird kein Nullzeichen hinzugefügt.
  • Leerzeichen : Alle Leerzeichen lösen einen Scan nach null oder mehr Leerzeichen aus . Die Anzahl und der Typ der Leerzeichen müssen in keiner Richtung übereinstimmen.
  • %lf  : Als doppelte Gleitkommazahl scannen. "Float" -Format mit dem "langen" Bezeichner.
  • %Lf  : Als lange doppelte Gleitkommazahl scannen. "Float" formatiert den "long long" -Spezifizierer.
  • %n  : Nichts wird erwartet. Die Anzahl der Zeichen, die bisher von der Eingabe verbraucht wurden, wird über den nächsten Zeiger gespeichert, der ein Zeiger auf int sein muss. Dies ist keine Konvertierung und erhöht nicht die von der Funktion zurückgegebene Anzahl.


Das Obige kann mit numerischen Modifikatoren und die in Verbindung verwendet werden l , L Modifizierungsmitteln, die für die „lange“ und „long long“ zwischen dem Prozentzeichen und dem Buchstaben stehen. Es können auch numerische Werte zwischen dem Prozentzeichen und den Buchstaben vor den long Modifikatoren vorhanden sein, die die Anzahl der zu scannenden Zeichen angeben. Ein optionales Sternchen ( * ) direkt nach dem Prozentzeichen zeigt an, dass das von diesem Formatbezeichner gelesene Datum nicht in einer Variablen gespeichert werden soll. Für diese abgelegte Variable sollte kein Argument hinter der Formatzeichenfolge enthalten sein.

Der ff Modifikator in printf ist in scanf nicht vorhanden, was zu Unterschieden zwischen den Ein- und Ausgabemodi führt. Die Modifikatoren ll und hh sind im C90-Standard nicht vorhanden, aber im C99-Standard.

Ein Beispiel für eine Formatzeichenfolge ist

"%7d%s %c%lf"

Die obige Formatzeichenfolge scannt die ersten sieben Zeichen als Dezimalzahl, liest dann die verbleibenden als Zeichenfolge, bis ein Leerzeichen, eine neue Zeile oder eine Registerkarte gefunden wird, verbraucht dann Leerzeichen, bis das erste Nicht-Leerzeichen gefunden wird, und verbraucht dann dieses Zeichen. und scannt schließlich die verbleibenden Zeichen als Doppel . Daher muss ein robustes Programm prüfen, ob der scanf Aufruf erfolgreich war, und geeignete Maßnahmen ergreifen. Wenn die Eingabe nicht das richtige Format hatte, befinden sich die fehlerhaften Daten weiterhin im Eingabestream und müssen verworfen werden, bevor neue Eingaben gelesen werden können. Eine alternative Methode, die dies vermeidet, besteht darin fgets , die eingelesene Zeichenfolge zu verwenden und anschließend zu untersuchen. Der letzte Schritt kann sscanf beispielsweise von ausgeführt werden.

Bei den vielen Float-Zeichen a, e, f, g entscheiden sich viele Implementierungen dafür, die meisten in denselben Parser zu reduzieren. Microsoft MSVCRT macht das mit e, f, g , während glibc das mit allen vier macht.

Sicherheitslücken

scanf ist anfällig für Formatierungs-String-Angriffe . Es sollte sorgfältig darauf geachtet werden, dass die Formatierungszeichenfolge Einschränkungen für die Zeichenfolgen- und Arraygröße enthält. In den meisten Fällen ist die Größe der Eingabezeichenfolge eines Benutzers beliebig und kann nicht bestimmt werden, bevor die scanf Funktion ausgeführt wird. Dies bedeutet, dass die Verwendung von %s Platzhaltern ohne Längenangaben von Natur aus unsicher ist und für Pufferüberläufe ausgenutzt werden kann . Ein weiteres potenzielles Problem besteht darin, dynamische Formatierungszeichenfolgen zuzulassen, z. B. Formatierungszeichenfolgen, die in Konfigurationsdateien oder anderen benutzergesteuerten Dateien gespeichert sind. In diesem Fall kann die zulässige Eingabelänge von Zeichenfolgengrößen nur angegeben werden, wenn die Formatierungszeichenfolge zuvor überprüft und Einschränkungen erzwungen wurden. Im Zusammenhang damit stehen zusätzliche oder nicht übereinstimmende Formatierungsplatzhalter, die nicht mit der tatsächlichen Vararg- Liste übereinstimmen . Diese Platzhalter können teilweise aus dem Stapel extrahiert werden oder unerwünschte oder sogar unsichere Zeiger enthalten, abhängig von der speziellen Implementierung von varargs .

Siehe auch

Verweise

Externe Links