4
respostas

[Bug] Bug ao colocar valor ≠ de inteiro na variavel

Não sei se isso vai ser abordado mais pra frente no curso, mas achei pertinente colocar essa dúvida aqui, já que pode surgir para outros que estiverem assistindo a mesma aula.

Na aula de número 05 "Fazendo vários chutes", ao inserir um valor diferente de inteiro na variável chute, o programa entra em um loop infinito e automático de chutes com valor 0.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Gostaria de saber por que isso acontece e qual seria a forma mais apropriada de corrigir. Visto que programamos para usuários e não para outros programadores, vejo claramente esse tipo de erro acontecendo se eu colocar outras pessoas pra jogar.

4 respostas

Qual valor diferente de inteiro vc digitou? E como está o seu código?

Normalmente os exemplos são simplificados para economizar tempo e complexidade e eventualmente os tratamentos de erros são introduzidos nos cursos mais pra frente.

O bug acontece com qualquer entrada diferente de inteiro, por exemplo ao digitar "f".

Segue o código:

#include<iostream> 
using namespace std; 

int main () {
    cout << "**************************************" << endl;
    cout << "* Bem-vindos ao jogo da adivinhação! *" << endl;
    cout << "**************************************" << endl; 

    const int NUM_SECRETO = 42;
    //cout << "O número secreto é: " << NUM_SECRETO << ". Não conte para ninguém!" << endl;
    bool errou = true;
    int tentativas = 0;

    double pontuacao = 1000.0;

    while(errou) {
        tentativas++;
        int chute; //declaracao de variavel
        cout << "Tentativa: " << tentativas << endl;
        cout << "Qual o valor do seu chute? ";
        cin >> chute; //comando cin serve para receber valores

        double pontos_perdidos = abs(chute - NUM_SECRETO)/2.0;
        pontuacao = pontuacao - pontos_perdidos;

        cout << "O valor do seu chute é: " << chute << endl;

        bool acerto = chute == NUM_SECRETO; 
        bool chute_maior = chute > NUM_SECRETO;

        if(acerto) {
            cout << "Parabéns! você acertou o número secreto." << endl;
            errou = false;
        }
        else if (chute_maior) {
            cout << "Seu chute foi MAIOR que o número secreto." << endl;
        }
        else {
            cout << "Seu chute foi MENOR que o número secreto." << endl;
        }
        cout << "**************************************" << endl;
    }

    cout << "Fim de jogo!" << endl;
    cout << "Número de tentativas: " << tentativas << endl;
    cout.precision(2);
    cout << fixed;
    cout << "Sua pontuação foi: " << pontuacao << endl;
    cout << "**************************************" << endl;
}

Desde já agradeço pela resposta.

Olá.

Você está fazendo:

bool acertou = true;

E depois:

while(acertou)

Eu não achei uma escolha muito boa. Você está dizendo que logo no início do programa, o usuário havia acertado, e depois mantém algo rodando enquanto o "acerto" é verdadeiro. Eu faria meio que o contrário:


bool acertou = false;

while(!acertou) { // enquanto a variável "acertou" for falsa. seria o mesmo de fazer "while(acertou == false)"

Como você está usando o std::cin para pegar a entrada e colocar num número inteiro, parece que ele faz algum comportamento estranho quando a entrada é uma letra, de forma que entra em um loop infinito. Admito que não conhecia esse comportamento, por isso não sei o explicar com clareza, mas você pode usar do seguinte para evitar que entre num loop infinito:

cin >> chute;

if(cin.fail()){
    cout << "Você digitou algo que não é uma letra." << endl;
}

Nicolas, Muito obrigado! O seu comentário ajudou bastante na minha pesquisa.

O comando "cin>>" não trata entradas inválidas. Logo se alguém digitar uma string, gera um exceção não tratada, que acaba gerando o loop infinito. Por isso se deve criar um código para tratar essa exceção.

No meu caso, a resolução mais simples que consegui implementar foi essa:

cin >> chute; //comando cin serve para receber valores
        if (!cin){
         cout << "Por favor, digite um número! ";

         cin.clear(); //limpa entradas erradas

         cin.ignore(256, '\n'); //descarta 
        }

Não sei se é a melhor forma, mas resolveu o problema. Se alguém souber de outra forma mais sofisticada para tratar essa exceção, seria ótimo conhecer.

O código completo ficou assim:

#include<iostream> //inclusao da biblioteca padrao para entrada e saida de dados
using namespace std; //comando usado para não precisar colocar "std::" antes das funcoes padroes

int main () {
    cout << "**************************************" << endl;
    cout << "* Bem-vindos ao jogo da adivinhação! *" << endl;
    cout << "**************************************" << endl; 

    const int NUM_SECRETO = 42;
    //cout << "O número secreto é: " << NUM_SECRETO << ". Não conte para ninguém!" << endl;
    bool acertou = false;
    int tentativas = 0;

    double pontuacao = 1000.0;

    while(!acertou) { //enquanto a variável "acertou" for falsa. seria o mesmo de fazer "while(acertou == false)"
        tentativas++;
        int chute; //declaracao de variavel
        cout << "Tentativa: " << tentativas << endl;
        cout << "Qual o valor do seu chute? ";
        cin >> chute; //comando cin serve para receber valores
        if (!cin){
         cout << "Por favor, digite um número! ";

         cin.clear(); //limpa entradas erradas

         cin.ignore(256, '\n'); //descarta 
        }

        double pontos_perdidos = abs(chute - NUM_SECRETO)/2.0; //abs funcao que devolve apenas o valor absoluto
        pontuacao = pontuacao - pontos_perdidos;

        cout << "O valor do seu chute é: " << chute << endl;

        bool acerto = chute == NUM_SECRETO; //bool é uma variavel booleana que recebe true or false
        bool chute_maior = chute > NUM_SECRETO;

        if(acerto) {
            cout << "Parabéns! você acertou o número secreto." << endl;
            acertou = true;
        }
        else if (chute_maior) {
            cout << "Seu chute foi MAIOR que o número secreto." << endl;
        }
        else {
            cout << "Seu chute foi MENOR que o número secreto." << endl;
        }
        cout << "**************************************" << endl;
    }

    cout << "Fim de jogo!" << endl;
    cout << "Número de tentativas: " << tentativas << endl;
    cout.precision(2);
    cout << fixed;
    cout << "Sua pontuação foi: " << pontuacao << endl;
    cout << "**************************************" << endl;
}

Agradeço a todos que responderam!