ciclo infinito em C ++ [duplicado]
-
06-07-2019 - |
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.)
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
.