Jak funguje scanf v C: vstup, formátování a běžné chyby

11

Vstup je mízou každého interaktivního programu. Bez něj jen používáte kalkulačku ve vzduchoprázdnu. V programovacím jazyce C je hlavním nástrojem pro získávání dat z klávesnice scanf. Je to jednoduché. Je to všudypřítomné. Je ale také proslulý svou bezohledností k chybám.

U jednoduchých skriptů nebo rychlých prototypů to udělá scanf. Čte se ze stdin (standardní vstup). Pokud píšete na klávesnici, vaše znaky jdou právě sem. Funkce je univerzální, ale postrádá spolehlivé zpracování chyb. Je jí jedno, jestli zadáte písmeno, když ona očekává číslo. Jednoduše to zamrzne, nebo v horším případě spadne váš program. To je důvod, proč je skvělý pro jednoduché úkoly, ale není vhodný pro produkční software.

Syntaxe a ampersand

Podívejme se na nejjednodušší možný případ použití. Potřebujete celé číslo. Vy to požadujete. Ušetříš to.

`scanf(“%d”, &b);”.

To je vše. Dva argumenty. Formátovat řetězec a cílovou proměnnou.

%d říká scanf, aby očekával celé číslo. Toto je stejný zástupný symbol, který používáte v printf. Proměnná b musí být deklarována jako int. Pokud ne, koledujete si o potíže.

Zde je část, která nováčky pokaždé mate: ampersand (& ).

„&b“ není překlep. Toto je ukazatel. Konkrétně se jedná o adresu proměnné b. scanf nepřijímá hodnotu, ale potřebuje místo v paměti, kam může zapisovat zadaná data. Zapomněli jste „&“. Váš kód se může zkompilovat. Ale kdy to spustíte? Kolaps. Segfault. Prázdnota. Program téměř jistě spadne, protože se pokusí zapsat data na náhodnou adresu paměti.

Formátování příznaků

scanf používá stejné konverzní specifikátory jako printf. Pokud znáte jedno, znáte i druhé. Ale záleží na kontextu.

  • Celé číslo : %d
  • Čísla s pohyblivou řádovou čárkou : %f
  • Jednoduché znaky : %c
  • Řádky : %s

Nepleťte si je. Nahraďte %f celým číslem a skončíte s nesmyslnými daty nebo pádem programu.

Proč scanf nestačí

Můžete řetězit volání scanf pro čtení více hodnot.

Toto funguje pro čísla. Je dostatečně čistý. Ale zkusit přečíst celý řádek textu? Tohle nebude fungovat. scanf se specifikátorem %s se zastaví na prvním prázdném znaku. Nečte celý řádek. A nezvládá přetečení vyrovnávací paměti bezpečně.

U skutečných programů byste se měli vyhnout použití scanf k zadávání textu. Místo toho použijte gets (který je zastaralý a nebezpečný) nebo nejlépe fgets. Tyto funkce čtou řádek po řádku do vyrovnávací paměti. Jakmile budete mít řetězec, můžete jej analyzovat. Můžete zkontrolovat chyby. Než se pokusíte převést, můžete se ujistit, že vstup vypadá jako číslo. scanf tento krok přeskočí. Předpokládá to, že víte, co děláte. Obvykle to nevíte.

Úmyslné zničení

Nejlepší způsob, jak se naučit C, není čtení dokumentace. Toto je chyba kompilátoru.

Vezměte tento úryvek:

Změňte to. Zhoršit to.

Odstraňte b z deklarací proměnných. Sledujte, jak kompilátor začíná křičet o nedefinované proměnné.

Odstraňte středník. Podívejte se, jak se syntaktická chyba šíří.

Odstraňte kudrnatou ortézu. Sledujte, jak se analyzátor zbláznil.

Odstraňte závorku. Sledujte zmatek