Domanda

    

Questa domanda ha già una risposta qui:

         

Sto imparando il C ++ e scrivo piccoli programmi mentre procedo. Quello che segue è uno di questi programmi:

// This program is intended to take any integer and convert to the
// corresponding signed char.

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(true){
    std::cin >> n;
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

Quando eseguo questo programma e mantengo gli input a valori assoluti ragionevolmente piccoli, si comporta come previsto. Ma quando inserisco input più grandi, ad es. 10000000000, il programma sputa ripetutamente lo stesso output. Alcune combinazioni di input causano comportamenti irregolari. Ad esempio:

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

Il programma sputa " 10 - > & Quot; fino a quando non viene ucciso. (Con questa particolare sequenza di input, l'output del programma cambia in modo irregolare.) Ho anche notato che l'output di valori di grandi dimensioni è determinato dall'input legale precedente e dal valore dell'input illegale corrente.

Cosa sta succedendo? (Non mi interessa risolvere il programma, è facile. Voglio capirlo.)

È stato utile?

Soluzione

Fondamentalmente il tuo flusso cin è in uno stato fallito e quindi ritorna immediatamente quando provi a leggerlo. Riscrivi il tuo esempio in questo modo:

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(std::cin >> n){
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

cin > > n restituirà un riferimento a cin , che puoi testare per " bontà " in un condizionale. Quindi, in sostanza, il " while (std :: cin > > n) " sta dicendo " mentre potrei ancora leggere correttamente dallo standard input, fai quanto segue "

EDIT: il motivo per cui ha emesso ripetutamente l'ultimo valore valido inserito è perché quello era l'ultimo valore letto correttamente in n, le letture non riuscite non cambieranno il valore di n

EDIT: come notato in un commento, puoi cancellare lo stato di errore e riprovare qualcosa del genere probabilmente funzionerebbe e ignorerebbe solo i numeri errati:

#include <iostream>
#include <climits>

int main() {
    signed char sch = 0;
    int n = 0;
    while(true) {
        if(std::cin >> n) {
            sch = n;
            std::cout << n << " --> " << sch << std::endl;
        } else {
            std::cin.clear(); // clear error state
            std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
        }
    }
}

Altri suggerimenti

Sì, Evan Teran ha già sottolineato molte cose. Una cosa che voglio aggiungere (dal momento che non posso ancora commentare il suo commento :)) è che devi mettere la chiamata a istream :: clear prima della chiamata a istream :: ignore. Il motivo è che istream :: ignore allo stesso modo rifiuterà di fare qualsiasi cosa se il flusso è ancora nello stato di errore.

Dato che sei su una macchina a 32 bit, 10000000000 è un numero troppo grande per essere rappresentato da un int. Anche la conversione di un int in un carattere ti darà solo da 0..255 o -128..127 a seconda del compilatore.

Un problema qui è che un char ha una dimensione di un byte e quindi può contenere solo un numero compreso tra -127 e 128. Un int invece , in genere è di 4 byte e può assumere valori molto più grandi. Il secondo problema è che stai inserendo un valore troppo grande anche per un int .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top