Pergunta

Esta questão já tem uma resposta aqui:

Estou aprendendo C ++ e escrever pequenos programas como eu ir junto. O seguinte é um tal programa:

// 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 eu executar este programa e manter as entradas no razoavelmente pequenos valores absolutos, ele se comporta como esperado. Mas quando eu entro entradas maiores, por exemplo, 10000000000, o programa cospe repetidamente a mesma saída. Algumas combinações de comportamento errático causa de entrada. Por exemplo:

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

O programa cospe "10 ->" até que esteja morto. (Com esta seqüência particular de entradas, as mudanças de saída do programa de velocidade de forma irregular.) Notei também que a saída de grandes valores é determinada pela entrada legal anterior, bem como o valor da entrada ilegal atual.

O que está acontecendo? (Eu não me importo sobre a fixação do programa, isso é fácil. Eu quero entendê-lo.)

Foi útil?

Solução

Basicamente seu fluxo cin está em uma falha estado e, portanto, retorna imediatamente quando você tenta lê-lo. Reescrever o seu exemplo como este:

#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 irá retornar uma referência a cin, que você pode testar para o "bem-ness" em uma condicional. Então, basicamente, o da "while(std::cin >> n)" está dizendo "enquanto eu ainda podia ler da entrada padrão com sucesso, faça o seguinte:"

EDIT: a razão pela qual repetidamente saída o último valor bom entrou é porque esse era o último valor lido com sucesso em n, a não lê não vai alterar o valor de n

EDIT: como mencionado em um comentário, você pode limpar o estado de erro e tente novamente algo como isto seria provavelmente trabalho e simplesmente ignorar números ruins:

#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
        }
    }
}

Outras dicas

Sim, Evan Teran apontou a maioria das coisas já. Uma coisa eu quero adicionar (desde que eu não posso comentar o seu comentário ainda :)) é que você deve colocar a chamada para istream :: clara antes a chamada para istream :: ignorar. A razão é que istream :: ignorar irá também simplesmente se recusam a fazer qualquer coisa se o fluxo ainda está em estado de falha.

Uma vez que você estiver em uma máquina de 32 bits, 10000000000 é o número um grande demais para ser representado por um int. Também converter um int para um char só vai te dar de 0..255 ou -128..127 dependendo do compilador.

Um problema aqui é que um char tem um tamanho de um byte, e, portanto, só pode armazenar um número entre -127 e 128. Um int por outro lado, é normalmente 4 bytes, e pode assumir valores muito maiores. Segundo problema é que você está entrando com um valor que é muito grande mesmo para um int.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top