2013-06-25 22 views
10
scanf(" %[^\n]",line); 

Un mio amico ha suggerito che l'utilizzo di fgets() per leggere una riga come input sarebbe un'idea molto migliore rispetto all'utilizzo di scanf() come nella dichiarazione di cui sopra. È giustificato?Leggere una riga usando scanf() non va bene?

+1

dovrebbe essere scanf ("% [^ \ n]", linea); chiudi il tutore nell'argomento .. –

+0

Lo è assolutamente. Suggerisco sempre di usare 'fgets()' ed evitare 'scanf()' completamente. –

+0

@RaghuSrikanthReddy Esempio perfetto del motivo per cui 'scanf()' non deve essere usato. –

risposta

17

char * fgets (char * str, int num, FILE * stream); è sicuro da usare perché evita il problema buffer overflow, esegue solo la scansione del numero num-1.

legge caratteri dal flusso e li memorizza come stringa C in str fino caratteri (num-1) sono stati letti o viene raggiunto sia una nuova linea o il file di fine, se precedente.

qui secondo argomento num è Numero massimo di caratteri da copiare in str (incluso il carattere null di chiusura).

Ad esempio, nel codice, una capacità di stringa di array è pari a 5 caratteri come indicato di seguito.

char str[5]; 
fgets (str, 5, fp); //5 =you have provision to avoid buffer overrun 

Utilizzando sopra il codice, se l'ingresso da fp è più lungo 4 caratteri, fgets() leggerà appena prima 4 caratteri poi aggiunge \0 (, e scartare altri caratteri di input supplementari, solo memorizza cinque char in str[]).

considerando scanf(" %[^\n]",str); leggerà fino \n non trovato e se la stringa di input è più lungo 4 caratteri scanf() causerà di buffer overflow (come scanf cercherà di accedere alla memoria oltre indice max 4 in str[]).

+1

Grazie per la spiegazione dettagliata. Scanf() sarà una scelta migliore, se non so per quanto tempo sarà la mia stringa di input? – amulous

+0

@amulous: Mr. YuHao ha dato un ottimo link. leggi qui, 'scanf()', 'printf()' le serie di funzioni sono valide per input/output formattati –

2

In poche parole: sì, fgets è una scelta migliore.

Ho visto il tuo specificatore di formato scanf e mi sono confuso. Capire esattamente cosa fa richiede un po 'di tempo per leggere le pagine man.

Inoltre, il codice scanf è suscettibile di sovraccaricare il buffer.

Mantenerlo semplice e ridurrà i costi di manutenzione ed eviterà di trovare errori!

+0

L'overflow del buffer è il diavolo. Fatto. Grazie. – amulous

6

C FAQ ha qualche spiegazione dettagliate sul problema scanf s':

Più in generale, scanf è progettato per relativamente strutturato, ingresso formattato (il suo nome è in realtà derivato da "SCAN formattato"). Se presti attenzione, ti dirà se è riuscito o meno, ma può dirti solo approssimativamente dove ha fallito, e non del tutto come o perché. Hai pochissime opportunità di fare un recupero degli errori.

vedere here per dettagli.

+0

un ottimo collegamento Grazie –

+0

Questo è un link molto utile. Grazie! – amulous

3

fgets sarà migliore di questo scanf. Ci possono essere seguenti problemi con scanf riportata nella OP

1) buffer overflow come suggerito dal @Grijesh

2) eventualmente successiva scanf dopo questo non funzionerà perché la nuova riga viene lasciato nel flusso di input. (se si dimentica uno spazio vuoto)

3

Sì fgets è il modo migliore e sicuro per leggere una riga dallo standard input.

Inoltre ci sarà più leggibilità nel codice. Guarda la dichiarazione scanf da te fornita.

Qualsiasi seconda persona che la vede sarà completamente confusa. Ma mentre ci sarà più readeablity per Fgets ed è facile da capire.

+5

Ti sei contraddetto. forse intendevi 'fgets' nella tua prima frase. –

+0

@Jim Balter Grazie per la correzione –

1

non utilizzare fgets (...) invece di utilizzare il seguente frammento:

char _x[7000]; 
    char* y; 
while (! feof (_f)) 
{ 
    fscanf(_f,"%[^\n]\n",_x); 
      y=x; 
}