validación de entrada para entrada numérica
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!!
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;
}
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;
}