Necesito ayuda, validación de números enteros

Iniciado por DarkSorcerer, 25 Noviembre 2013, 11:19 AM

0 Miembros y 1 Visitante están viendo este tema.

DarkSorcerer

Este es un problema que ocurre al ingresar por error un caracter no numerico.

Tengo un programa en que desde el main se despliega un menu (dentro de un ciclo infinito), para que el usuario pueda elegir la opcion que necesito, yo decidi usar un switch para ir a los submenus, la cosa es que el switch solo acepta numeros enteros, ademas, dentro del while hay un bloque try/catch, por que decidi implementar una forma de lanzar una excepcion cuando detecte el problema y para que el programa no se detenga. La excepcion se envia a una funcion "indentificarExcepcion", que no es nada mas que imprimir por pantalla el tipo de error , por ejemplo, cuando se ingrese mal en el menu, mandara un 1 y al procesar la excepcion, saldra por pantalla "Error: Ingrese caracteres no numericos".
El problema que mas me complica es que si ingreso una letra, pareciera ser que el ciclo while se vuelve loco e imprime el menu infinitas veces, por ahi lei que es necesario usar el clear para restablecer "cin" y tambien usar el flag cin.fail(), pero no tengo los resultados esperados. Les dejo mi codigo.


Código (cpp) [Seleccionar]


#include <cstdlib>
#include <iostream>
#include <windows.h>
#include "Operaciones.h"

using namespace std;
using namespace operaciones;

void opcion1(){
   
    cout <<"\e[2J";
    cout <<"\n::::: MATRIZ TRASPUESTA :::::\n";   
    continuar();
   
}

void opcion2(){
   
    cout <<"\e[2J";
    cout <<"\n::::: ELIMINAR VALOR :::::\n";     
    continuar();
   
}

void opcion3(){
   
    cout <<"\e[2J";
    cout <<"\n::::: ELIMINAR COLUMNA :::::\n";
    continuar();
   
}

void opcion4(){
   
    cout <<"\e[2J";
    cout <<"\n::::: ELIMINAR MATRIZ :::::\n"; 
    continuar();
   
}

void opcion5(){
   
    cout <<"\e[2J";
    cout <<"\n::::: SUMA ESPECIAL DE UNA MATRIZ :::::\n";
    continuar();
   
}

void opcion6(){
   
    cout <<"\e[2J";
    cout <<"\n::::: AGREGAR VALOR :::::\n";   
    continuar();
   
}

void opcion7(){
   
    cout <<"\e[2J";
    cout <<"\n::::: INGRESAR NUEVA MATRIZ :::::\n";
    continuar();
   
}

void opcion8(){
   
    cout <<"\e[2J";
    cout <<"\n::::: TODAS LAS MATRICES DEL SISTEMA :::::\n";
    continuar();
   
}

int main(int argc, char** argv) {
   
    int opcion;
   
    while(true){
       
        desplegarMenu();
       
        try{
           
            cin >> opcion;
           
            if(cin.fail()){
               
                cin.clear();
                throw 1;
               
            }

            switch(opcion){
               
                case 1:
                   
                    opcion1();
                   
                    break;
                   
                case 2:
                   
                    opcion2();
                   
                    break;
                   
                case 3:
                   
                    opcion3();
                   
                    break;
                   
                case 4:
                   
                    opcion4();
                   
                    break;
                   
                case 5:
                   
                    opcion5();
                   
                    break;
                   
                case 6:
                   
                    opcion6();
                   
                    break;
                   
                case 7:
                   
                    opcion7();
                   
                    break;
                   
                case 8:
                   
                    opcion8();
                   
                    break;
                   
                case 9:
                   
                    salir();
                   
                    break;
            }
           
        }catch(int e){
           
            identificarExcepcion(e);
           
        }
       
       
    }

    return 0;
}


xaps

Primero de todo, no has puesto un default en el switch y es muy recomendable hacerlo en este caso, ya que con eso te aseguras que cualquier otro valor de la variable opcion que no haya sido explicitado se evalúe.

Aquí tienes más información: http://c.conclase.net/curso/?cap=005c

Ahora bien, si con añadir default no solucionas tu problema, podrías cambiar el tipo de la variable opcion a char, y validar en cada iteración del bucle que el valor del char corresponda a los números del 1 al 9.

Tabla de valores ASCII: http://imagenes.mailxmail.com/cursos/imagenes/3/6/codigo-de-caracteres-ascii_5163_19_1.jpg

Saludos
"The programmers of tomorrow are the wizards of the future" - Gave Newel

rir3760

Cita de: DarkSorcerer en 25 Noviembre 2013, 11:19 AMEl problema que mas me complica es que si ingreso una letra, pareciera ser que el ciclo while se vuelve loco e imprime el menu infinitas veces, por ahi lei que es necesario usar el clear para restablecer "cin" y tambien usar el flag cin.fail(), pero no tengo los resultados esperados.
El problema se debe a que el operador ">>" solo consumirá los caracteres validos para la conversión indicada, si el carácter en turno no es valido se queda en el bufer de la entrada estándar para ser procesado eventualmente.

Para solucionarlo solo debes eliminar el resto de la linea mediante sync o ignore. Un ejemplo sencillo del uso de este ultimo:
Código (cpp) [Seleccionar]
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <limits>
using std::numeric_limits;

int main()
{
   int numero;
   
   while (true) {
      cout << "Introduce un numero: ";
      if (cin >> numero)
         break;
      else {
         cin.clear();
         cin.ignore(numeric_limits<int>::max(), '\n');
      }
   }
   
   cout << "El numero es " << numero << endl;
   
   return 0;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

do-while

¡Buenas!

Cuando intentas leer un entero pero introduces un caracter, se activa el failbit de istream. Por lo tanto primero tendrás que intentar leer el dato. Luego comprobar si se ha activado el failbit y si asi ha sucedido, resetearlo y vaciar el buffer de entrada:

Código (cpp) [Seleccionar]

while((cin>>dato).fail()) //comprobamos los flags de error con la referencia que devuelve el operador >>
{
    cin.clear(); //reseteamos los flags
    while(cin.get() != '\n'); //leemos todo lo que quede en la entrada
    //Si quieres pones un mensaje de error y vuelves a solicitar los datos
}

//Al salir del bucle sabemos que hemos leido el dato que corresponde


¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!