validación de entrada para entrada numérica

Resuelto MacUsers asked hace 12 años • 2 respuestas

Soy muy nuevo en este mundo de C++ y estoy intentando escribir una función de validación de entrada para una contraseña numérica. Esto es lo que obtuve hasta ahora:

#include <iostream>
#include <limits>
using namespace std;

void isNumeric(int &iN)
{
    while (1) {
        cin >> iN;

        if (cin.fail()) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Only 'numeric' value(s) are allowed: ";
            continue;
        }

        // alpha-numeric entry also not allowed 
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        if (cin.gcount() >  1) continue;

        // check against the -ve value
        if (iN <= 0 ) continue;

    break;
    }
}

int main()
{
    int x;

    cout << "Enter your number: ";
    isNumeric(x);
    cout << "You've entered: " << x << endl;

    return 0;
}

Está funcionando bien para valores incorrectos, pero no sale del ciclo al realizar una entrada válida. ¿Alguna idea de lo que me estoy perdiendo aquí? ¡¡Salud!!


Error del guión de James Kanze:

test.cpp: In function ‘bool parseNumber(const string&, int&)’:
test.cpp:11:20: error: no match for ‘operator>>’ in ‘text >> results’
test.cpp:11:20: note: candidates are:
/usr/include/c++/4.6/bits/basic_string.tcc:998:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::basic_string<_CharT, _Traits, _Alloc>&)
/usr/include/c++/4.6/bits/istream.tcc:957:5: note: template<class _CharT2, class _Traits2> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT2*)
/usr/include/c++/4.6/bits/istream.tcc:925:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT&)
/usr/include/c++/4.6/istream:709:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char&)
/usr/include/c++/4.6/istream:714:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char&)
/usr/include/c++/4.6/istream:756:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char*)
/usr/include/c++/4.6/istream:761:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char*)
test.cpp:11:42: error: ‘const string’ has no member named ‘peek’
test.cpp:11:52: error: ‘EOF’ was not declared in this scope


Nuevo código: uso getline()y validación como cadena. Gracias a todos (especialmente a James Kanze) por ayudarme. Esto prácticamente funciona aquí.

void isNumeric( int &iN )
{
    string sN; 

    while (1) {
        getline(cin, sN);

        bool valNum = true;
        for ( unsigned iDx=0; iDx < sN.length(); iDx++ )
            if ( !isdigit(sN[iDx]) ) { 
                valNum = false;
                break;
            }   

        if ( !valNum ) { 
            cout << "Wrong entry; Try again: ";
            continue;
        }   

        stringstream sStream (sN );
        sStream >> iN; 

        if ( iN<=0 ) {
            cout << "Cannot be 0; Try again: "; 
            continue;
        }     
    break;   
    }   
}

¿Hay margen para más mejoras? ¡¡Salud!!

MacUsers avatar Apr 17 '12 00:04 MacUsers
Aceptado

Esto parece una entrada orientada a líneas. En cuyo caso, la solución habitual es utilizar getline:

bool parseNumber( std::string const& text, int& results )
{
    std::istringstream parser( text );
    return parser >> results >> std::ws && parser.peek() == EOF;
}

int getNumber()
{
    int results;
    std::string line;
    while ( ! std::getline( std::cin, line ) || ! parseNumber( line, results ) ) 
    {
        std::cin.clear();
        std::cout << "Only 'numeric' value(s) allowed:";
    }
    return results;
}
James Kanze avatar Apr 16 '2012 18:04 James Kanze

Si no se puede realizar la conversión, la secuencia misma se evalúa como falsa, por lo que puedes hacer esto:

int get_int() {
    int i;
    std::cout << "Please enter a number: " << std::endl;
    while(!(std::cin >> i)) {
        std::cin.clear();   //clear flags
        //discard bad input
        std::cin.ignore(std::numeric_limits<std::streamsize>::max()); 
        std::cout << "Incorrect, must be numeric: " << std::endl;
    }
    return i;
 }
111111 avatar Apr 16 '2012 17:04 111111