Toto je často diskutované téma, plné názor, ale zajímavé, nic méně. Všiml jsem si, že velká většina z těch, které již reagovaly na podobné otázky na tomto webu padat na stranu fgets()
. Já jsem jeden z nich. Najít fgets()
mnohem lepší použít pro vstup uživatele, než scanf()
s několika výjimkami. scanf()
je zvažován mnoho jako sub-optimální metodu pro zpracování uživatelského vstupu. Například
"...to vám řekne, zda se to podařilo nebo nepodařilo, ale můžu říct jen přibližně, kde to nepodařilo, a už vůbec ne, jak nebo proč. Ty
mají velmi málo příležitostí udělat žádnou chybu."
(jamesdlin). Ale v zájmu pokusu rovnováhy, začneme s odkazem na tuto diskuzi.
Pro vstup uživatele, který pochází z stdin
, tj. vstup z klávesnice, fgets()
bude lepší volbou. To je mnohem více tolerantní v tom, že řetězec to čte může být plně validovány před konverzí je pokus o
Jeden z mála případů pomocí formuláře scanf(): fscanf() by být v pořádku používat, může být při převodu vstup z velmi řízené zdroje, tj. od čtení čistě formátovaný soubor s opakující se předvídatelné pole.
Pro více diskuse, toto srovnání dvou zdůrazňuje další výhody a nevýhody obou.
Edit: na adresu OP doplňující otázku o přetečení:
"Jedna věc, kterou chci se zeptat, je: i když jsme použít fgets co se stane, když uživatel zadat více znaků, než je hranice (tím myslím hodně
znaků), má to vést k přetečení vyrovnávací paměti? Pak, jak se vypořádat s
to?"
[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm je pěkně navržen tak, aby se zabránilo přetečení vyrovnávací paměti, jednoduše tím, že pomocí jeho parametry správně, např.:
char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);
Tím se zabrání vstupu větší než velikost vyrovnávací paměti, z které jsou zpracovávány, čímž se zabrání přetečení.
dokonce i pomocí scanf()
předcházení přetečení vyrovnávací paměti je docela rovně vpřed: Použití specifikátor šířky ve formátu string. Pokud si chcete přečíst vstup pro příklad a limit velikosti vstupu od uživatele do 100 znaků, kód by zahrnovat následující:
char buffer[101] = {0};// includes space for 100 + 1 for NULL termination
scanf("%100s", buffer);
^^^ width specifier
Nicméně s čísly, přetečení není tak příjemné použití scanf()
. Prokázat, použijte tento jednoduchý kód, zadejte dvě hodnoty uvedené v komentáři jeden za běhu:
int main(void)
{
int val = 0;
// test with 2147483647 & 2147483648
scanf("%d", &val);
printf("%d\n", val);
return 0;
}
Pro druhou hodnotu, můj systém hodí následující:
NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error
`
Zde je třeba číst v řetězci, pak postupujte s řetězec na číslo konverze pomocí jednoho z strto_()
funkce: strtol(), strtod(), ...). Oba patří schopnost test na přetečení , než způsobí run-time upozornění nebo chyba. Všimněte si, že použití atoi()
, atod()
nebude chránit od přetečení.