scanf-formatsträng - scanf format string
En scanf formatsträng ( scan f ormatted) är en styrparameter som används i olika funktioner för att ange layouten på en ingångssträng . Funktionerna kan sedan dela strängen och översätta till värden av lämpliga datatyper . Sträng scanning funktioner ofta levereras i standardbibliotek .
Uttrycket "scanf" kommer från C-biblioteket , som populariserade denna typ av funktion, men sådana funktioner föregår C, och andra namn används, såsom readf i ALGOL 68 . scanf-formatsträngar, som ger formaterad inmatning ( parsing ), kompletterar strängar med printf-format , som ger formaterad output ( mall ). Dessa ger enkel funktionalitet och fast format jämfört med mer sofistikerade och flexibla parsers eller mallmotorer, men är tillräckliga för många ändamål.
Historia
Mike Lesk : s bärbara in / ut-bibliotek , inklusive scanf , blev officiellt en del av Unix i version 7 .
Användande
Den scanf funktion, som finns i C , läser ingång för nummer och andra datatyper från standard in (ofta en kommandorad gränssnitt eller liknande typ av en text användargränssnitt ).
Följande C-kod läser ett variabelt antal oformaterade decimala heltal från standardinmatningsströmmen och skriver ut var och en av dem på separata rader:
#include <stdio.h>
int main(void)
{
int n;
while (scanf("%d", &n) == 1)
printf("%d\n", n);
return 0;
}
Efter att ha bearbetats av programmet ovan, en oregelbundet fördelad lista över heltal som
456 123 789 456 12
456 1
2378
visas konsekvent med varandra som:
456 123 789 456 12 456 1 2378
Så här skriver du ut ett ord:
#include <stdio.h>
int main(void)
{
char word[20];
if (scanf("%19s", word) == 1)
puts(word);
return 0;
}
Oavsett vilken datatyp programmeraren vill att programmet ska läsa &n måste argumenten (som ovan) vara pekare som pekar på minnet. I annat fall fungerar inte funktionen korrekt eftersom den försöker skriva över fel delar av minnet snarare än att peka på minnesplatsen för variabeln du försöker få inmatning för.
I det sista exemplet en adress-of operator ( & ) är inte används för argumentet: som word är namnet på en matris av char , som sådan är (i alla sammanhang där det utvärderas till en adress) som motsvarar en pekare till den första element i matrisen. Medan uttrycket &word numeriskt skulle utvärderas till samma värde, har det semantiskt en helt annan betydelse genom att det står för adressen till hela arrayen snarare än ett element i den. Detta faktum måste hållas i åtanke när man tilldelar scanf utdata till strängar.
Som scanf är avsedd att läsa endast från standardinmatning, har många programmeringsspråk med gränssnitt , såsom PHP , derivat som sscanf och fscanf inte sig scanf själv.
Formatera strängspecifikationer
Formateringsplatshållare i scanf är mer eller mindre densamma som den i printf dess omvänd funktion. Som i printf n$ definieras POSIX-tillägget .
Det finns sällan konstanter (dvs. tecken som inte formaterar platshållare ) i en formatsträng, främst för att ett program vanligtvis inte är utformat för att läsa känd data, även om scanf det accepteras om det uttryckligen anges. Undantaget är ett eller flera blankstegstecken , som förkastar alla mellanslagstecken i ingången.
Några av de mest använda platshållarna följer:
-
%a: Skanna ett flytpunkt i dess hexadecimala notation. -
%d: Skanna ett heltal som ett signerat decimaltal . -
%i: Skanna ett heltal som ett signerat nummer. Liknar%d, men tolkar talet som hexadecimalt när det föregås av0xoch oktalt när det föregås av0. Till exempel skulle strängen031läsas som 31 med%doch 25 med%i. Flagganhi%hianger konvertering till ashortochhhkonvertering till achar. -
%u: Skanna efter decimalunsigned int(Observera att i C99-standarden är ingångsvärdet minus tecken valfritt, så om ett minustecken läses upp kommer inga fel att uppstå och resultatet blir de två komplementet till ett negativt tal, sannolikt ett mycket stort värde. Sestrtoul().) På motsvarande sätt%husöker efter enunsigned shortoch%hhuefter enunsigned char. -
%f: Skanna ett flytande nummer i normal notering ( fast punkt ). -
%g,%G: Skanna ett flytpunktsnummer i antingen normal eller exponentiell notation.%ganvänder gemener och%Gversaler. -
%x,%X: Skanna ett heltal som ett osignerat hexadecimalt tal. -
%o: Skanna ett heltal som ett oktalt tal. -
%s: Skanna en teckensträng . Skanningen avslutas i det vita utrymmet . Ett null-tecken lagras i slutet av strängen, vilket innebär att bufferten som tillhandahålls måste vara minst ett tecken längre än den angivna ingångslängden. -
%c: Skanna ett tecken (tecken). Ingen null karaktär läggs till. - mellanslag : Alla blankstegstecken utlöser en genomsökning av noll eller fler mellanslagstecken . Antalet och typen av blankstegstecken behöver inte matchas i någon riktning.
-
%lf: Skanna som ett dubbelt flytnummer. "Float" -format med "long" -specifikatorn. -
%Lf: Skanna som ett långt dubbelt flytpunktsnummer. "Float" formaterar "long long" -specifikatorn. -
%n: Ingenting förväntas. Antalet tecken som konsumeras så långt från ingången lagras genom nästa pekare, som måste vara en pekare till int. Detta är inte en konvertering och ökar inte antalet som returneras av funktionen.
Ovanstående kan användas i sammansättning med numeriska modifierare och l , L modifierare som står för "lång" och "lång lång" mellan procentsymbolen och bokstaven. Det kan också finnas numeriska värden mellan procentsymbolen och bokstäverna, före long eventuella modifierare, som anger antalet tecken som ska skannas. En valfri asterisk ( * ) direkt efter procentsymbolen anger att den referens som läses av denna formatspecifikator inte ska lagras i en variabel. Inget argument bakom formatsträngen bör inkluderas för den tappade variabeln.
Den ff modifierare i printf inte är närvarande i scanf, vilket orsakar skillnader mellan sätt ingång och utgång. Den ll och hh modifierings inte förekommer i C90-standarden, men förekommer i C99-standarden.
Ett exempel på en formatsträng är
"%7d%s %c%lf"
Ovanstående formatsträng skannar de första sju tecknen som ett decimaltal, läser sedan de återstående som en sträng tills ett mellanslag, ny linje eller flik hittas, förbrukar sedan mellanslag tills det första icke-vita tecknet hittas och förbrukar sedan det tecknet, och slutligen skannar de återstående karaktärerna som en dubbel . Därför måste ett robust program kontrollera om scanf samtalet lyckades och vidta lämpliga åtgärder. Om ingången inte var i rätt format kommer felaktiga data fortfarande att finnas i ingångsströmmen och måste kasseras innan ny ingång kan läsas. En alternativ metod, som undviker detta, är att använda fgets och sedan undersöka den inlästa strängen. Det sista steget kan till exempel göras sscanf .
När det gäller de många flottypstecknen a, e, f, g väljer många implementeringar att kollapsa mest i samma parser. Microsoft MSVCRT gör det med e, f, g , medan glibc gör det med alla fyra.
Sårbarheter
scanf är sårbart för formatsträngattacker . Stor försiktighet bör iakttas för att formateringssträngen innehåller begränsningar för sträng- och matrisstorlekar. I de flesta fall är ingångssträngstorleken från en användare godtycklig och kan inte bestämmas innan scanf funktionen körs. Detta innebär att användningen av %s platshållare utan längdspecifikationer i sig är osäker och kan utnyttjas för buffertöverflöden . Ett annat potentiellt problem är att tillåta dynamiska formateringssträngar, till exempel formateringssträngar lagrade i konfigurationsfiler eller andra användarkontrollerade filer. I det här fallet kan den tillåtna ingångslängden för strängstorlekar inte anges om inte formateringssträngen kontrolleras i förväg och begränsningar tillämpas. Relaterade till detta är ytterligare eller felaktiga formateringsplatshållare som inte matchar den faktiska vararg- listan. Dessa platshållare kan extraheras delvis från stacken eller innehålla oönskade eller till och med osäkra pekare, beroende på den speciella implementeringen av varargs .
Se även
Referenser
externa länkar
- - Systemgränssnittsreferens, den enda UNIX-specifikationen , nummer 7 från The Open Group
- C ++ referens för
std::scanf