Ver Mensaje Individual
  #4 (permalink)  
Antiguo 20/10/2015, 09:57
aguml
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 10 meses
Puntos: 3
Respuesta: ¿Es error mío?Si es así, ¿cómo puedo solucionarlo?

Cita:
Iniciado por eferion Ver Mensaje
Buenas.

Lo primero bienvenido al foro.

Antes de comentar tu problema te aviso, el código tiene que ir decorado con la etiqueta del lenguaje correspondiente. Mira el combobox "Highlight" y verás la lista de lenguajes.

Vale, ahora tu problema.

Código C++:
Ver original
  1. int opcion;
  2. cin>>opcion;

Ese código va a almacenar un int en opción... si no se introduce un número válido, entonces almacenará un 0. Da igual lo que introduzcas... si cin no puede convertir la entrada a número almacenará un 0. ¿Cómo detectar esa situación?

Bueno, hay una sobrecarga que te indica si la operación ha podido completarse de forma correcta:

Código C++:
Ver original
  1. int opcion;
  2. bool ok = std::cin >> opcion;
  3. if ( !ok )
  4.   std::cout << "ERROR";

El problema es que después de un error el buffer se queda con basura, lo que provocará que el programa empiece a funcionar raro. La solución pasa por limpiar el buffer de entrada cuando se produzca un error:

Código C++:
Ver original
  1. int opcion;
  2. bool ok = std::cin >> opcion;
  3. if ( !ok )
  4. {
  5.   std::cout << "ERROR";
  6.   cin.clear();
  7.   cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  8. }

clear limpia los bits de error, la siguiente línea elimina caracteres del buffer de entrada hasta que encuentre un salto de línea '\n'. Si no encuentra un salto de línea borrará tantos caracteres como se indica en ese chorizo que te voy a detallar:

  • streamsize es un alias del tipo de dato empleado internamente por los buffers para indizar la información. Lo normal es que sea tipo int.
  • numeric_limits es un template que permite recuperar los límites para cada tipo de dato. En este caso se está llamando a max() que contiene el valor máximo que puede ser almacenado en un tipo de dato dado... ¿qué tipo? el que determine streamsize que, como hemos dicho, suele ser int.
Es decir, en la mayoría de los casos el ejemplo se podría simplificar a:

Código C++:
Ver original
  1. int opcion;
  2. bool ok = std::cin >> opcion;
  3. if ( !ok )
  4. {
  5.   std::cout << "ERROR";
  6.   cin.clear();
  7.   cin.ignore(std::numeric_limits<int>::max(), '\n');
  8. }

¿Por qué no sustituir numeric_limits por un valor en concreto? pues porque si por ejemplo sustituyes esa llamada por 2^31-1 y compilas el programa en un entorno en el que int ocupa 2 bytes en vez de 4 acabarás teniendo problemas.

Por supuesto también tienes la opción de leer una cadena de caracteres. Entonces compruebas si la secuencia introducida se puede convertir a número y, en caso negativo mostrar un mensaje de error... hay más alternativas, pero creo que con estas dos te podrás manejar.

Un saludo.
Interesante lo que indicas. Yo he usado ignore () sin argumentos creo recordar ¿hay algún problema por usar ese?