Attenzione: fflush(stdin);
potrebbe essere un comportamento non definito. Leggi: Why fflush(stdin)
is wrong?
int fflush(FILE *ostream);
I ostream
indica un flusso di output o un flusso di aggiornamento in cui il ultima operazione non era ingresso, la funzione fflush
provoca alcuna dati non scritti per quel flusso da consegnare all'ambiente ospite da scrivere nel file; in caso contrario, lo behavior
è Undefined
.
si può provare un ciclo e leggere fino EOF
o \n
dato this FAQ entry invece di fflush(stdin)
come ho suggerito di seguito nella mia risposta.
Edit: grazie a @Jonathan Leffler:
Ci sono piattaforme in cui fflush(stdin)
è completamente definito (come estensione non standard su quella piattaforma). L'esempio principale è una famiglia ben nota di sistemi noti collettivamente come Windows. Specifiche Microsoft di int fflush(FILE *stream);
Se stream
è aperto per l'immissione, fflush
cancella il contenuto del buffer.
Ho ulteriori dubbi nel codice; cosa è M
nell'espressione unsigned int b = pow(2,M-1);
? Dovrebbe essere un errore se non lo definisci. Stai postando il codice completo?
voi per quanto riguarda la logica di rilevamento degli errori:
ri-leggere il valore se l'utente inserisce un invalido
No, scanf()
non restituisce un codice di errore. Restituisce il numero di conversioni riuscite.
int scanf (const char * format, ...);
Return Value
In caso di successo, la funzione restituisce il numero di elementi della lista degli argomenti pieno successo.Questo conteggio può corrispondere a il numero previsto di articoli o essere inferiore (pari a zero) a causa di un errore corrispondente , un errore di lettura o la portata della fine del file.
Se un errore di lettura o verifica viene raggiunta la fine del file-mentre lettura, l'indicatore corretto è impostato (feof
o ferror
). E, se si verifica prima che i dati possano essere letti correttamente, viene restituito EOF
.
Se un errore codifica avviene interpretazione caratteri estesi, la funzione imposta errno
a EILSEQ
.
Quindi in realtà a seconda dell'errore riscontrato il valore restituito può essere zero, EOF. È necessario utilizzare la macro int ferror (FILE * stream);
e errno
per il rilevamento degli errori (controllare l'esempio fornito al collegamento).
errori possibili a causa di input non valido può essere:
EILSEQ
: sequenza di byte di ingresso non forma un carattere valido.
EINVAL
: argomenti non sufficienti; o il formato è NULL.
ERANGE
: una conversione intera supera la dimensione che può essere memorizzata nel tipo intero corrispondente.
Controllare scanf manual per l'elenco completo.
Motivo ciclo infinito:
Il sistema tiene traccia di quale ingresso è stato visto finora. Ogni chiamata a scanf
riprende da dove l'ultimo ha interrotto l'input corrispondente. Ciò significa che se si è verificato un errore con il precedente scanf
, l'input che non è riuscito a corrispondere è ancora lasciato non letto, come se l'utente digitato avanti. Se non si presta attenzione per scartare l'input dell'errore e viene utilizzato un loop per leggere l'input, il programma può rimanere intrappolato in un loop infinito.
Così, per esempio nel codice:
x = scanf("%u", &a);
// ^
// need a number to be input
Ma supponiamo che non viene inserito un numero, ma una stringa non valida viene inserito per esempio "name"
(anziché un numero, come dici tu). Ciò causerà l'errore della funzione scanf()
quando si tenta di associare un numero intero senza segno ("%u"
) e la parola "name"
non viene letta. Quindi, la volta successiva, il ciclo scanf()
non attende l'input dell'utente, ma prova a convertire nuovamente "nome".
Similmente se l'ingresso fosse 29.67
, il "%u
" restituisce i primi due soli caratteri (il 29
), lasciando la .67
ingresso come da leggere per la chiamata successiva al scanf()
.
Anche se l'input è corretto, come 29
, la fine riga che ha terminato l'input è ancora lasciata non letta.Normalmente questo non è un problema poiché la maggior parte delle conversioni salta automaticamente spazi bianchi iniziali come la nuova riga finale dalla riga precedente. Tuttavia, alcune conversioni ("%c"
e "%["
) non salteranno alcun spazio bianco iniziale, quindi è necessario farlo manualmente.
Per evitare questo infinito loop Un suggerimento:
(ricordate: come ho consigliato l'uso di ferror()
, errore di valore è preferibile per rilevare input non valido Inoltre, è solo per l'apprendimento scopo e se. bisogno di attuare una seria applicazione si dovrebbe usare fgets(str)
invece di scanf()
seguita da quella analizzare str
input per verificare se l'input è valido)
input:
//fflush(stdout); //use if needed, as \n used in printf no need of fflush-stdout
printf("\nEnter any integer: ");
x = scanf("%u", &a); // always wait for new symbols
printf("%u", a);
if(x == 0){ // x=0, if error occurred
// read all unread chars
while ((ch = getchar()) != '\n' && ch != EOF);
goto input;
}
E 'solo un suggerimento che sarà p funziona in modo ossibile con il tuo codice (ha funzionato per me, il tuo codice + gcc). Ma se si utilizza questa tecnica in modo non corretto, può lasciare un bug nel codice:
Leggi How do I flush the input buffer?
Se si è certi che i dati indesiderato è nel flusso di input, è possibile utilizzare alcuni dei seguenti codici snippet per rimuoverli. Tuttavia, se si chiama quando non ci sono dati nel flusso di input, il programma sarà attendere fino a quando non lo è, il che dà risultati indesiderati.
in questo caso è possibile utilizzare il ciclo while. Per favore guarda il codice modificato sotto – stev