2015-09-03 20 views
25

Sono completamente nuovo in C++ e sto provando a scrivere un programma estremamente semplice, ma sto avendo problemi con l'inizializzazione di un intero. Ho spogliato giù ad un programma molto piccolo che ha ancora il problema:Perché cin, in attesa di un int, modifica la variabile int corrispondente a zero in caso di input non valido?

#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "Please enter your age\n"; 
    int age = -1; 
    cin >> age; 
    cout <<"\n\n Your age is " << age << "\n\n"; 
} 

ho letto che se si tenta di inserire una stringa, ad esempio abc alla variabile age, quindi l'input non dovrebbe riuscire e il valore dovrebbe essere lasciato da solo e pertanto è necessario stampare Your age is -1.

Tuttavia, quando eseguo questo programma e digito abc, viene stampato Your age is 0. Perché?

+0

Eccellente TestCase.Ma, purtroppo, un dupe. –

risposta

33

Il comportamento si desidera osservare cambiato nel 2011. Fino ad allora:

Se l'estrazione non riesce (ad esempio, se una lettera è stato immesso in cui si prevede una cifra), il valore viene lasciato invariato e failbit è impostato.

Ma dal momento che C++ 11:

Se l'estrazione non riesce, lo zero viene scritto il valore e failbit è impostato. [...]

(da cppr.)

+9

Qual è la logica per questo? –

+9

Immagino che sia potenzialmente inefficiente richiedere che il vecchio valore venga tenuto in giro solo nel caso in cui la lettura fallisca. Ora possiamo iniziare immediatamente a sovrascrivere il vecchio valore e quindi cancellarlo se c'è un errore. –

+5

Se l'efficienza fosse solo la ragione, avrebbe più senso lasciare il valore non specificato in caso di errore. Sembra anche strano che rompano il codice esistente al fine di eliminare una semplice mossa in memoria in un'operazione che di solito sarà dominata dai tempi di accesso al disco (o dalla velocità di digitazione, se stdin in un terminale). – Ray

4

Con il compilatore ho testato contro (gcc 4.8.4), il valore è impostato a zero (per l'ingresso 'abc') indipendentemente da quale versione dello standard che compilo contro. Si noti inoltre che è impostato su valori minimi/massimi se si fornisce un numero intero valido al di fuori dell'intervallo supportato della variabile a cui si sta assegnando.

Un altro punto importante, tuttavia, è che ignorare i flag di errore è una ricetta per il disastro. Una volta che si è verificato un errore nell'input, qualsiasi input successivo è sospetto (senza hack come ignore()). Situazioni come questa sono un buon candidato per l'utilizzo della gestione delle eccezioni.

Ecco come potrei implementare ciò che si sta cercando di fare (ma, ancora una volta, considerando il caso di più ingressi, il recupero da errori è un business disordinato):

cin.exceptions(~std::ios::goodbit); 
try { cin >> age; } 
catch (std::ios::failure const &) 
    { 
    age=-1; 
    cin.clear(); 
    cin.ignore(999,'\n'); 
    } 

o senza eccezioni:

cin >> age; 
if (cin.fail()) age=-1, cin.clear(), cin.ignore(999,'\n'); 

vedi qui per domande simili:

Qui sono up-to-date documentazione per l'operatore in questione:

+0

Una domanda correlata a cui ho risposto qualche tempo fa: [C++ input failure: più input in una singola istruzione] (http://stackoverflow.com/q/29244708) – nobar

+0

@LightnessRacesinOrbit: Questo è ciò che accade quando si digita tutto da solo anziché lasciare che un IDE decida quale dovrebbe essere il tuo stile. :) – nobar

+0

No, non lo è! O non dovrebbe essere ..... Stai dicendo che sei diventato così dipendente dal tuo IDE per la formattazione del codice che sei fisicamente incapace di eseguirlo da solo, nonostante abbia il tempo infinito per fare un tentativo prima di postare? Perché, se è così, è davvero scoraggiante. :( –

Problemi correlati