Questo è comunemente discusso argomento, pieno di parere interessante, ma che non di meno. Ho osservato che una grande maggioranza di quelli che hanno già risposto a domande simili su questo sito cadere sul lato della fgets()
. Io sono uno di loro. Trovo fgets()
per essere molto meglio per l'input dell'utente di scanf()
con poche eccezioni. scanf()
è considerato da molti come sub-ottimale metodo per la gestione dell'input utente. Per esempio
"...ti dirà se è riuscita o meno, ma posso dire solo circa, dove non è riuscito, e non a tutti come o perché. Si
hanno poche opportunità di fare qualche errore di recupero."
(jamesdlin). Ma nell'interesse di tentare equilibrio iniziare citando questa discussione.
L'input di un utente che proviene da stdin
, cioè l'input da tastiera, fgets()
sarà una scelta migliore. È molto più indulgente che stringa legge può essere convalidato prima della conversione è tentato
Una delle poche volte che utilizza una forma di scanf(): fscanf() sarebbe bene utilizzare sia durante la conversione di input da una sorgente controllata, cioè dalla lettura strettamente formattato il file con la ripetizione di prevedibile campi.
Per maggiori informazioni, questo il confronto dei due mette in evidenza ulteriori vantaggi e gli svantaggi di entrambi.
Edit: per risolvere OP ulteriore domanda su overflow:
"Ancora una cosa che voglio chiedere è: anche quando si usa fgets cosa succede se l'utente di immettere i caratteri oltre il confine (voglio dire un sacco di
caratteri), non porta a buffer overflow? Quindi come trattare con
esso?"
[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm è ben progettato per prevenire l'overflow del buffer, semplicemente utilizzando i parametri correttamente, ad esempio:
char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);
Questo impedisce l'ingresso maggiore della dimensione del buffer di essere trattati, evitando l'overflow.
anche utilizzando scanf()
prevenire buffer overflow è piuttosto semplice: Utilizzare un identificatore di larghezza nella stringa di formato. Se volete leggere l'input, per esempio, e il limite di dimensione di input da utente a 100 caratteri max, il codice è la seguente:
char buffer[101] = {0};// includes space for 100 + 1 for NULL termination
scanf("%100s", buffer);
^^^ width specifier
Tuttavia, con i numeri di overflow non è così bello che utilizza scanf()
. Per dimostrare, utilizzare questo semplice codice, inserendo i due valori indicati nel commento uno per eseguire:
int main(void)
{
int val = 0;
// test with 2147483647 & 2147483648
scanf("%d", &val);
printf("%d\n", val);
return 0;
}
Per il secondo valore, il mio sistema genera il seguente:
NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error
`
Qui potete leggere una stringa, poi seguire con una stringa di conversione numero utilizzando uno dei strto_()
funzioni: strtol(), strtod(), ...). Entrambi includono la possibilità per il test di overflow prima di causare un run-time di avviso o di errore. Si noti che l'utilizzo atoi()
, atod()
non protegge da overflow sia.