fgets() a gets() v programování C

Úvod

Funkce fgets() a gets() slouží v programovacím jazyce C k načítání řetězců ze vstupního proudu. Přestože obě tyto funkce plní podobný účel, existují mezi nimi zásadní rozdíly. V tomto článku si tyto funkce podrobně probereme, včetně jejich odlišností, výhod a nevýhod. To vám pomůže rozhodnout, kterou z nich zvolit pro konkrétní situaci.

fgets()

Funkce fgets() načítá řádek ze vstupního proudu a ukládá ho do zadané paměti (bufferu). Funkce vyžaduje tři argumenty:

  1. Ukazatel na buffer, do kterého se bude řetězec ukládat.
  2. Maximální počet znaků, které se mají načíst.
  3. Vstupní proud (např. standardní vstup stdin).

Příklad použití:


char buffer[100];
fgets(buffer, 100, stdin);

V uvedeném příkladu funkce fgets() načte řádek ze standardního vstupu (stdin) a uloží ho do bufferu buffer, který má velikost 100 znaků. Funkce vrací ukazatel na buffer, nebo NULL v případě chyby.

gets()

Funkce gets() se podobá funkci fgets(), ale má několik klíčových rozdílů:

  1. Nepřijímá argument pro maximální počet znaků.
  2. Načítá celý řádek až do konce řádku nebo do konce souboru.
  3. Nepřidává ukončovací znak '\0' na konec řetězce.

Příklad použití:


char buffer[100];
gets(buffer);

V tomto příkladu gets() načítá řádek ze standardního vstupu a ukládá ho do buffer o velikosti 100 znaků. Funkce však sama o sobě nepřidává ukončovací znak '\0'. Proto buffer může obsahovat „odpadní data“ za samotným řetězcem.

Rozdíly mezi fgets() a gets()

Hlavním rozdílem mezi fgets() a gets() je způsob zpracování ukončovacího znaku '\0'. Funkce fgets() ho automaticky přidává na konec načteného řetězce, zatímco gets() nikoliv. Toto může vést k problémům, pokud s tím nepočítáte při práci s výsledkem funkce gets().

Dalším zásadním rozdílem je, že fgets() akceptuje maximální počet znaků jako argument, zatímco gets() nikoliv. To znamená, že při použití gets() může dojít k přetečení bufferu, pokud neznáte přesnou délku načítaného řetězce.

Výhody a nevýhody

fgets()

  • Výhody:
    • Automaticky přidává ukončovací znak '\0'.
    • Omezuje počet načtených znaků, čímž předchází přetečení bufferu.
  • Nevýhody:
    • Může být pomalejší než gets() pro velmi dlouhé řetězce.

gets()

  • Výhody:
    • Pro dlouhé řetězce je rychlejší než fgets().
  • Nevýhody:
    • Nepřidává ukončovací znak '\0'.
    • Může vést k přetečení bufferu, pokud je načítaný řetězec delší než buffer.

Kdy použít fgets()

Použijte fgets() v situacích, kdy:

  • Potřebujete řetězec s ukončovacím znakem '\0'.
  • Znáte maximální délku řetězce, který chcete načíst.
  • Chcete zabránit přetečení bufferu.

Kdy použít gets()

Použijte gets() v situacích, kdy:

  • Nechcete automatické přidání ukončovacího znaku '\0'.
  • Neznáte maximální délku načítaného řetězce.
  • Potřebujete co nejvyšší výkon při načítání velmi dlouhých řetězců.

Závěr

Funkce fgets() a gets() jsou v jazyce C užitečnými nástroji pro načítání řetězců. Přestože se jejich účel zdá být stejný, existují mezi nimi důležité rozdíly. Volba té správné funkce závisí na konkrétních požadavcích. Pokud požadujete ukončovací znak a znáte maximální délku, použijte fgets(). Jestliže potřebujete maximální rychlost pro dlouhé řetězce, nebo vám ukončovací znak nevadí, můžete použít gets(). Je však potřeba pamatovat na rizika s ní spojená.

Často kladené otázky

  1. Která funkce je rychlejší: fgets() nebo gets()?

    Většinou je gets() rychlejší pro velmi dlouhé řetězce, zatímco fgets() je rychlejší pro krátké řetězce.

  2. Kdy použít funkci scanf() namísto fgets() nebo gets()?

    Funkci scanf() použijte v případě, že chcete načíst řetězec a zároveň ho konvertovat na jiný datový typ, například číslo.

  3. Je možné zabránit přetečení bufferu při používání funkce gets()?

    Ano, je možné použít funkci strncat() společně s gets() a omezit tak počet načtených znaků.

  4. Jak zpracovat řetězec načtený pomocí gets() tak, aby obsahoval ukončovací znak?

    Můžete použít funkci strcat() pro přidání ukončovacího znaku na konec řetězce.

  5. Kterou funkci použít při načítání řetězce ze souboru?

    Při čtení ze souboru je obvykle lepší použít funkci fgets(), protože automaticky přidává ukončovací znak a předchází přetečení bufferu.

  6. Kterou funkci použít při načítání řetězce z konzole?

    Pro načítání řetězce z konzole můžete použít jak fgets(), tak gets(). Nicméně fgets() je preferována, protože přidává ukončovací znak a předchází přetečení bufferu.

  7. Co se stane, pokud fgets() nebo gets() narazí na konec souboru?

    V případě, že funkce fgets() nebo gets() dosáhnou konce souboru, vrátí hodnotu NULL.

  8. Jak ošetřit chybu při používání funkcí fgets() nebo gets()?

    Můžete zkontrolovat návratovou hodnotu funkce. Pokud je NULL, došlo k chybě.