Řetězec formátu scanf - scanf format string - Wikipedia
![]() | tento článek potřebuje další citace pro ověření.Květen 2010) (Zjistěte, jak a kdy odstranit tuto zprávu šablony) ( |
A řetězec formátu scanf (skenovat formatted) je kontrolní parametr používaný v různých funkce určit rozvržení vstupu tětiva. Funkce pak mohou rozdělit řetězec a přeložit jej na příslušné hodnoty typy dat. Funkce skenování řetězců jsou často dodávány standardně knihovny.
Termín "scanf" pochází z C knihovna, který popularizoval tento typ funkce, ale takové funkce předcházejí C a používají se další názvy, například čtení
v ALGOL 68. řetězce formátu scanf, které poskytují formátovaný vstup (analýza ), doplňují se řetězce formátu printf, které poskytují formátovaný výstup (šablonování ). Poskytují jednoduchou funkčnost a pevný formát ve srovnání se sofistikovanějšími a flexibilnějšími analyzátory nebo šablonami, ale jsou dostatečné pro mnoho účelů.
Dějiny
Mike Lesk je přenosná knihovna vstupů / výstupů, počítaje v to scanf
, se oficiálně stala součástí Unixu v Verze 7.[1]
Používání
The scanf
funkce, která se nachází v C, čte vstup pro čísla a další typy dat z standardní vstup (často a rozhraní příkazového řádku nebo podobný druh a textové uživatelské rozhraní ).
Následující kód C čte proměnný počet neformátovaných desetinných míst celá čísla ze standardního vstupního proudu a vytiskne každý z nich na samostatné řádky:
#zahrnout <stdio.h>int hlavní(prázdnota){ int n; zatímco (scanf("% d", &n) == 1) printf("% d n", n); vrátit se 0;}
Po zpracování výše uvedeným programem se zobrazí nepravidelně rozmístěný seznam celých čísel, jako je
456 123 789 456 12456 1 2378
se bude zobrazovat vždy jako:
4561237894561245612378
Tisk slova:
#zahrnout <stdio.h>int hlavní(prázdnota){ char slovo[20]; -li (scanf("% 19s", slovo) == 1) uvádí(slovo); vrátit se 0;}
Bez ohledu na to, jaký datový typ programátor chce, aby program četl, argumenty (např & n
výše) musí být ukazatele ukázal na paměť. Jinak funkce nebude fungovat správně, protože se bude snažit přepsat nesprávné části paměti, místo aby ukazovala na paměťové místo proměnné, pro kterou se pokoušíte získat vstup.
V posledním příkladu operátor adresy (&
) je ne použito pro argument: jako slovo
je jméno pole z char
, jako takový je (ve všech kontextech, ve kterých se vyhodnocuje na adresu) ekvivalentní ukazateli na první prvek pole. Zatímco výraz &slovo
by číselně vyhodnotil na stejnou hodnotu, sémanticky, má úplně jiný význam v tom, že znamená adresu celého pole, spíše než jeho prvek. Tuto skutečnost je třeba mít na paměti při přiřazování scanf
výstup na řetězce.
Tak jako scanf
je určen ke čtení pouze ze standardního vstupu, mnoho programovacích jazyků s rozhraní, jako PHP, mají deriváty jako např sscanf
a fscanf
ale ne scanf
sám.
Specifikace formátu řetězce
Formátování zástupné symboly v scanf
jsou víceméně stejné jako v printf
, jeho reverzní funkce. Stejně jako v printf, rozšíření POSIX n $
je definováno.[2]
Zřídka existují konstanty (tj. Znaky, které se neformátují zástupné symboly ) ve formátovacím řetězci, hlavně proto, že program obvykle není určen ke čtení známých dat scanf
přijímá je, pokud je výslovně uvedeno. Výjimkou je jedna nebo více mezery znaky, které zahodí všechny prázdné znaky ve vstupu.[2]
Následují některé z nejčastěji používaných zástupných symbolů:
%A
: Naskenuje číslo s plovoucí desetinnou čárkou v hexadecimálním zápisu.% d
: Naskenovat celé číslo jako podepsané desetinný číslo.% i
: Naskenuje celé číslo jako podepsané číslo. Podobný% d
, ale interpretuje číslo jako hexadecimální když předchází0x
a osmičkový když předchází0
. Například řetězec031
bude číst jako 31 pomocí% d
a 25 pomocí% i
. Vlajkah
v%Ahoj
označuje převod na akrátký
ahh
převod na achar
.% u
: Vyhledat desetinná místanepodepsané int
(Všimněte si, že ve standardu C99 je znaménko mínus vstupní hodnoty volitelné, takže pokud se čte znaménko mínus, nevzniknou žádné chyby a výsledkem bude doplněk dvou záporné číslo, pravděpodobně velmi velká hodnota. Vidětstrtoul ()
.[ověření se nezdařilo ]) Odpovídajícím způsobem,% hu
vyhledábez znaménka krátký
a% hhu
pronepodepsaný znak
.%F
: Skenovat a plovoucí bod číslo v normálu (pevný bod ) notace.%G
,%G
: Naskenuje číslo s plovoucí desetinnou čárkou v normální nebo exponenciální notaci.%G
používá malá písmena a%G
používá velká písmena.%X
,%X
: Naskenovat celé číslo jako nepodepsané hexadecimální číslo.%Ó
: Naskenovat celé číslo jako osmičkový číslo.% s
: Skenovat a řetězec znaků. Skenování končí v mezery. A nulový znak je uložen na konci řetězce, což znamená, že dodaná vyrovnávací paměť musí být alespoň o jeden znak delší než zadaná délka vstupu.%C
: Naskenuje znak (znak). Ne nulový znak je přidáno.- mezery: Jakékoli prázdné znaky spustí skenování na nulu nebo více mezery postavy. Počet a typ prázdných znaků se nemusí shodovat v obou směrech.
% lf
: Skenovat jako a dvojnásobek číslo s plovoucí desetinnou čárkou. Formát „Float“ se specifikátorem „long“.% Lf
: Skenovat jako a dlouhý dvojitý číslo s plovoucí desetinnou čárkou. Formát „float“ specifikátor „long long“.% n
:
Výše uvedené lze použít ve směsi s numerickými modifikátory a l
, L
modifikátory, které představují „dlouhý“ a „dlouhý dlouhý“ mezi symbolem procenta a písmenem. Mezi symbolem procenta a písmeny před znakem procent mohou být také číselné hodnoty dlouho
modifikátory, pokud existují, které určují počet znaků, které mají být skenovány. Volitelné hvězdička (*
) hned za symbolem procenta označuje, že datum přečtené tímto specifikátorem formátu nemá být uloženo v proměnné. U této zrušené proměnné by neměl být zahrnut žádný argument za formátovacím řetězcem.
The ff
modifikátor v printf není přítomen v scanf, což způsobuje rozdíly mezi režimy vstupu a výstupu. The ll
a hh
modifikátory nejsou obsaženy ve standardu C90, ale jsou obsaženy ve standardu C99.[3]
Příkladem formátovacího řetězce je
„% 7d% s% c% lf“
Řetězec výše uvedeného formátu prohledá prvních sedm znaků jako celé číslo v desítkové soustavě, poté zbývající přečte jako řetězec, dokud nenajde mezeru, nový řádek nebo tabulátor, poté spotřebuje mezery, dokud nebude nalezen první znak, který není mezerou, a poté tento znak spotřebuje, a nakonec naskenuje zbývající znaky jako a dvojnásobek. Proto musí robustní program zkontrolovat, zda scanf
hovor byl úspěšný a proveďte příslušná opatření. Pokud vstup nebyl ve správném formátu, budou chybná data stále ve vstupním proudu a musí být zahozena, než bude možné číst nový vstup. Alternativní metodou, která se tomu vyhýbá, je použití fgets
a poté zkontrolujte načtený řetězec. Poslední krok lze provést pomocí sscanf
, například.
V případě mnoha znaků typu float a, e, f, gMnoho implementací se rozhodlo sbalit většinu do stejného analyzátoru. Microsoft MSVCRT to dělá s e, f, g,[4] zatímco glibc dělá to se všemi čtyřmi.[2]
Zranitelnosti
scanf
je zranitelný vůči formátování řetězcových útoků. Je třeba věnovat velkou pozornost tomu, aby formátovací řetězec obsahoval omezení velikostí řetězců a polí. Ve většině případů je velikost vstupního řetězce od uživatele libovolná a nelze ji určit před scanf
funkce je spuštěna. To znamená, že použití % s
zástupné symboly bez specifikátorů délky jsou ze své podstaty nezabezpečené a zneužitelné pro přetečení vyrovnávací paměti. Dalším potenciálním problémem je povolení řetězců dynamického formátování, například formátování řetězců uložených v konfiguračních souborech nebo jiných souborech ovládaných uživatelem. V tomto případě nelze zadat povolenou vstupní délku velikostí řetězce, pokud není předem zkontrolován formátovací řetězec a nejsou vynucena omezení. S tím souvisí další nebo neodpovídající zástupné symboly formátování, které neodpovídají skutečnému vararg seznam. Tyto zástupné symboly mohou být částečně extrahovány ze zásobníku nebo obsahovat nežádoucí nebo dokonce nezabezpečené ukazatele, v závislosti na konkrétní implementaci varargy.
Viz také
Reference
- ^ McIlroy, M. D. (1987). Čtenář Research Unix: anotované výňatky z Programmer's Manual, 1971–1986 (PDF) (Technická zpráva). CSTR. Bell Labs. 139.
- ^ A b C Linux Programátor Manuál - Funkce knihovny –
- ^ Standard C99, §7.19.6.2 "Funkce fscanf" alinea 11.
- ^ "znaky pole typu skenování". docs.microsoft.com.
externí odkazy
- Specifikace Single UNIX, Vydání 7 od Otevřená skupina - Reference systémových rozhraní,
- C ++ reference pro
std :: scanf