2012-10-15 17 views
20

Da cplusplus.comQual è l'equivalente di gets() in C11?

La più recente revisione della norma C (2011) ha definitivamente rimosso questa funzione dalla sua specifica

La funzione è sconsigliata a C++ (a partire dal 2011 standard, che segue C99 + TC3).

Volevo solo sapere qual è l'alternativa a gets() in standard C11?

+2

fgets (..., ..., stdin) –

risposta

15

In C11 gets è stato sostituito da gets_s che ha la seguente dichiarazione:

char *gets_s(char *str, rsize_t n); 

Questa funzione leggerà al massimo n-1 caratteri da stdin in *str. Questo per evitare la vulnerabilità di overflow del buffer inerente a gets. La funzione fgets è anche un'opzione. Da http://en.cppreference.com/w/c/io/gets:

Il gets() funzione non esegue il controllo dei limiti, pertanto, questa funzione è estremamente vulnerabile al buffer-overflow attacchi. Non può essere usato in modo sicuro (a meno che il programma non sia eseguito in un ambiente che limita ciò che può apparire su stdin). Per questo motivo, la funzione è stata deprecata nella terza rettifica dello standard C99 e completamente rimossa nello standard C11. fgets() e gets_s() sono le sostituzioni consigliate.

Non utilizzare mai gets().

Dato che gets_s è definito in un'estensione dello standard, solo opzionalmente implementato, probabilmente si dovrebbe scrivere i tuoi programmi usando fgets invece. Se si utilizza su stdin, il programma verrà compilato anche nelle versioni precedenti di C. Ma tenere presente la differenza nel comportamento: quando gets_s ha letto n-1 caratteri continua a leggere finché non viene raggiunta una nuova riga o fine del file , scartando l'input. Quindi, con gets_s stai sempre leggendo un'intera riga, anche se solo una parte di essa può essere restituita nel buffer di input.

+6

Va notato che 'gets_s' è opzionale, non è necessario essere presente se l'implementazione non definisce' __STDC_LIB_EXT1__', e se lo fa, è necessario '__STDC_WANT_LIB_EXT1__' definito a 1 (se non è definito affatto, è implementazione- definito se le funzioni nell'appendice K sono incluse nelle rispettive intestazioni). –

+6

'fgets' dovrebbe essere usato. 'gets_s' è un'interfaccia opzionale che esiste solo su Windows ed è stata menzionata nello standard solo per ragioni politiche.Praticamente tutti fuori dalla SM trovano le interfacce _s fuorviate e dannose. Secondo quanto riferito, il comportamento standardizzato di alcune o tutte le interfacce _s differisce dalle sole implementazioni esistenti (quelle MS), rendendo il loro uso ancora più dannoso. –

+0

Sospetto che tu abbia frainteso il comportamento di gets_s. Proprio come Fgets, legge al massimo n-1 caratteri. La differenza è che gets_s si ferma se incontra un nuovo carattere di linea. Niente nello standard indica che continua a leggere dopo n-1. Non confondere la versione standard con varie implementazioni non standard esistenti prima di C11. – Lundin

4

Secondo man 3 gets, fgets.

+0

L'equivalente di ottiene nello standard C11 è gets_s, anche se tecnicamente dovrebbe essere la stessa cosa di fgets (..., stdin); – Lundin

+1

"In un allegato facoltativo aggiunto per motivi politici" difficilmente "nello standard C11". Non troverai una versione conforme a C11 delle funzioni _s da nessuna parte, perché nessuno ha intenzione di implementarle. –

+2

@ R .. L'allegato K di C11 è normativo, anche se non è obbligatorio implementarlo. In pratica, ciò significa che le implementazioni C non possono più contenere funzioni get_s strane e non standard che hanno un comportamento che si scontra con lo standard. Scommetto anche che GCC implementerà queste funzioni: il compilatore adora le funzionalità opzionali, ridondanti e inutili. Vorrei comunque consigliare fgets(), per motivi di compatibilità. – Lundin

8

Altri hanno già risposto alla domanda. Per completezza, questa è la raccomandazione dello standard C:

ISO9899: 2011 K.3.5.4.1/6

pratica raccomandata

La funzione fgets permette ai programmi correttamente scritti per elaborare in modo sicuro le linee di ingresso troppo lunghe per memorizzare nel risultato array. In generale, ciò richiede che i chiamanti di Fgets prestino attenzione a la presenza o l'assenza di un carattere di nuova riga nell'array dei risultati. Considerare l'utilizzo di fgets (insieme a qualsiasi elaborazione necessaria basata sui caratteri new-line) anziché su gets_s.

Pertanto, se possibile, utilizzare codici.

EDIT

comportamento gets_s è specificato di essere:

ISO9899: 2011 K.3.5.4.1/4

Descrizione

La funzione gets_s legge al massimo un inferiore al numero di caratteri specificato da n dal flusso puntato da stdin, nella matrice puntata da s. Nessun ulteriore caratteri viene letto dopo un carattere di nuova riga (che viene scartato) o dopo la fine del file. Il carattere di nuova riga scartato non conta al numero di caratteri letti. Un carattere nullo viene scritto immediatamente dopo l'ultimo carattere letto nell'array.

Se viene rilevato end-of-file e nessun carattere è stato letto nella matrice, o se un errore di lettura si verifica durante il funzionamento, allora s [0] è impostato al carattere nullo, e gli altri elementi di s prendono valori non specificati.

+3

Si noti che 'gets_s()' segnala una violazione del vincolo se non c'è né una nuova riga né EOF all'interno dei caratteri 'n-1'; è un errore ottenere una linea troppo lunga. –