How to clear numeric menu buffer when typing strings?

1

How to implement a menu that reads numeric values and indicates error (message on screen) when receiving characters and strings? The code below worked for individual characters through if(std::cin >> opcao) , but for strings it stores the buffer and replaces it several times - depending on the size of the string.

Code:

#include <iostream>
#include "Elemento.h"

int main()
{
    int opcao;

    Elemento e = 0;

    Elemento::mostrarMenu();

    do{
        std::cout << "Opção: ";

        if(std::cin >> opcao){          

            switch(opcao){

                case 1:
                    Elemento::adicionar(e);
                    Elemento::listar();
                    break;

                case 2:
                    Elemento::listar();
                    break;

                case 3:
                    std::cout << "Encerrando." << std::endl;
                    break;

                default:
                    std::cout << "Opção inválida." << std::endl;
                    break;      
            }// fim switch()

            std::cin.clear();
        }//fim if cin
        else{

            std::cin.clear();
            std::cin.ignore();
            std::cout << "Digite um número válido" <<std::endl;
        }

      std::cin.clear();
      std::cin.ignore();
    }
    while(opcao != 3); // fim do - while()
}

Compile command:

clang++ -Wall -ansi -O main.cpp Elemento.cpp -o Elemento

Execution:

Menu: 1 - Adicionar. 2 - Mostrar. 3 - Sair. Opção: r Digite um número válido Opção: rafael Digite um número válido Opção: Digite um número válido Opção: Digite um número válido Opção: _

How can I display the warning in else only once, even if the user types a string?

I put several cin.ignore and cin.clear that improved the situation, but did not solve. What is the simplest (and / or most efficient) way to deal with this situation?

    
asked by anonymous 17.04.2015 / 15:29

1 answer

1

Your case is very simple. You just have to read the rest of the string. You can use the following code in the else.

else
    {
        //bad token
        cin.clear();
        string badToken;
        cin >> badToken;
        cerr << "Entrada invalidade encontrada: " << badToken << endl;
    }

So when the loop starts again the buffer will be empty. You can also read all characters with a cin.get () in a while, but I find it easier to read everything in a string than once. And tb cin.clear () does not clear the buffer it only resets the cin state to the default. Then you can remove cin.clear () and cin.ignore () after the else.

    
19.04.2015 / 01:43