2010-03-09 15 views
9

cosa succede quando si cin >> lettera in variabile int? Ho provato un semplice codice per aggiungere 2 numeri int, prima li ho letti, piuttosto che aggiungerli. Ma quando inserisco la lettera, fallisce e stampa tonnellate di numeri sullo schermo. Ma cosa causa questo errore? Voglio dire, mi aspettavo che caricasse e usasse il codice ASCII di quella lettera.C++ carattere per int

+1

Puoi pubblicare il codice che hai usato? –

risposta

3

se si esegue il cast esplicito su un int, verrà utilizzato il codice ASCII, altrimenti non eseguirà il cast da solo su int, in modo da ottenere gli strani risultati ottenuti.

1

Si potrebbe utilizzare int istream::get();

10

io suppone che si abbia il codice come questo:

int n; 
while (someCondition) { 
    std::cin >> n; 
    ..... 
    std::cout << someOutput; 
} 

Quando si entra qualcosa che non può essere letta come un intero, il flusso (std :: cin) entra in un fallito stato e tutti i seguenti tentativi di input falliscono fintanto che non si ha a che fare con l'errore di input.

È possibile verificare il successo di un'operazione di input:

if (!(std::cin >> n)) //failed to read int 

ed è possibile ripristinare il flusso di un buono stato ed eliminare caratteri non elaborati (l'ingresso che ha causato l'errore in ingresso):

std::cin.clear(); 
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Un'altra possibilità è accettare l'input in una variabile stringa (che raramente fallisce) e provare a convertire la stringa in int.

Questo è un problema molto comune con l'input e ci dovrebbero essere tonnellate di thread su di esso qui e altrove.

+0

Grazie, quindi se ho capito bene, stdout invia effettivamente il codice ASCII al programma, ma std :: cin riconosce che tipo è e lo usa in quel modo. – Vit

+1

Se si prevede di immettere la variabile ** int **, allora "123" è OK ma "xyz" rende l'operazione di input non riuscita. Lo stream riceve solo una sequenza di caratteri dall'input, ma esegue conversioni sul tipo richiesto e indica i fallimenti in modo tale che puoi e dovresti testare. – visitor

1

Il problema è che quando si legge in una variabile intera, utilizzando flussi C++, il metodo di input si aspetta caratteri che possono costituire un numero, come '+', '-', '0' ... '9 '. Qualsiasi carattere che non è in questo set termina l'input e viene creato un numero da questi caratteri.

Per ottenere il valore ASCII di un carattere, è necessario immettere i dati in una variabile char. Internamente, ha il valore ASCII (a condizione che il programma non stia leggendo i caratteri a 16 bit o EBCDIC). Se si desidera visualizzare il valore ASCII, sarà necessario emettere la variabile char come numero intero (in genere richiede un cast prima dell'output).

Se la lettura di un intero non riesce, il programma deve informare l'utente che l'immissione non è corretta. Il programma potrebbe richiedere che l'utente inserisca nuovamente il numero prima che il programma possa elaborare i dati di input.

1

Quando si sta facendo qualcosa di simile:

int x; 
cin >> x; 

si indica C++ per aspettare di leggere un int da tastiera. In realtà, quando si inserisce qualcosa che non è uno int, il flusso di input (input standard, in questo caso) rende inutilizzabile a causa del suo stato di errore.

Ecco perché personalmente preferisco sempre leggere le stringhe e convertirle in numeri se necessario. Ci sono funzioni di conversione nella parte C della libreria standard C++ che può aiutare con questo.

double cnvtToNumber(const std::string &num) 
{ 
    char * ptr; 
    double toret = strtod(num.c_str(), &ptr); 

    if (*ptr != 0) { // If it got to the end of the string, then it is correct. 
     throw std::runtime_error("input was not a number"); 
    } 
    return toret; 
} 

Qui si converte un numero e si rileva se la conversione è corretta.strtod(s) si fermerà solo quando trova la fine della stringa o uno spazio. Al fine di evitare gli spazi ingannare la funzione di uscita, si può aver bisogno di una funzione di assetto:

std::string &trim(std::string &str) 
{ 
    // Remove trailing spaces 
    unsigned int pos = str.length() -1; 

    while(str[ pos ] == ' ') { 
     --pos; 
    } 

    if (pos < (str.length() -1)) { 
     str.erase(pos + 1); 
    } 

    // Remove spaces at the beginning 
    pos = 0; 
    while(str[ pos ] == ' ') { 
     ++pos; 
    } 

    if (pos < 1) { 
     str.erase(0, pos); 
    } 

    return str; 
} 

Ora si può tranquillamente leggere da console (o qualsiasi altro flusso di input):

int main() 
{ 
    std::string entry; 

    try { 
     std::getline(std::cin, entry); 
     int age = cnvtToNumber(trim(entry)); 

     std::cout << age << std::endl; 
    } catch(const std::exception &e) { 
     std::cerr << e.what() << std::endl; 
    } 
} 

Naturalmente è possibile perdere la precisione se leggi sempre double e poi convertirli. Esistono funzioni specifiche per i numeri interi (strtol(s)), nel caso in cui si desideri approfondire ulteriormente.