2012-05-31 10 views
7

Este es el códigoCómo hacer cin tomar sólo números

double enter_number() 
{ 
    double number; 
    while(1) 
    { 

     cin>>number; 
     if(cin.fail()) 
     { 
      cin.clear(); 
      cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
      cout << "Invalid input " << endl; 
     } 
     else 
     break; 
     cout<<"Try again"<<endl; 
    } 
    return number; 
} 

Mi problema es que cuando entro en algo así como 1x, luego 1 se toma como entrada sin darse cuenta el carácter que se quede fuera de otra carrera. ¿Hay alguna manera de hacerlo funcionar con cualquier número real, p. 1.8?

+0

¿Leer todo en una cadena y analizar la entrada en consecuencia? – Rhexis

+0

Utilice cin.get() y luego verifique si hay caracteres EOF. – Ansari

Respuesta

7

me gustaría utilizar std::getline y std::string para leer toda la línea y sólo salir del bucle cuando se puede convertir toda la línea de un doble.

#include <string> 
#include <sstream> 

int main() 
{ 
    std::string line; 
    double d; 
    while (std::getline(std::cin, line)) 
    { 
     std::stringstream ss(line); 
     if (ss >> d) 
     { 
      if (ss.eof()) 
      { // Success 
       break; 
      } 
     } 
     std::cout << "Error!" << std::endl; 
    } 
    std::cout << "Finally: " << d << std::endl; 
} 
19

Cuando cin encuentra una entrada que no puede leer correctamente en la variable especificada (como ingresar un carácter en una variable entera), entra en un estado de error y deja la entrada en su búfer.

Tiene que hacer varias cosas para manejar adecuadamente este escenario.

  1. Tienes que comprobar este estado de error.
  2. Tienes que borrar el estado de error.
  3. Tiene que manejar alternativamente los datos de entrada que generaron el estado de error, o eliminarlos y volver a llamar al usuario.

El siguiente código proporciona uno de los numerosos métodos para hacer estas tres cosas.

#include<iostream> 
#include<limits> 
using namespace std; 
int main() 
{ 

    cout << "Enter an int: "; 
    int x = 0; 
    while(!(cin >> x)){ 
     cin.clear(); 
     cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
     cout << "Invalid input. Try again: "; 
    } 
    cout << "You enterd: " << x << endl;   
} 

Se podía pasar en un valor grande para cin.ignore como 1000 y es probable que se comporten exactamente el mismo para todos los propósitos prácticos.

También puede probar cin después del intento de entrada y manejarlo de esa manera, algo así como if (! Cin) {// limpiar el error}.

Mira la referencia istream para otras funciones miembro para manejar estado de flujo: http://cplusplus.com/reference/iostream/istream/

+0

Esa línea 'cin.ignore' la está limpiando, ¿verdad? – Jeff

+0

@Jeff Sí, vacía el búfer. También puedes usarlo cuando usas cin con getline mientras tomas entradas, ya que Cin deja '\ n' en el búfer y no elimina (creo, no estoy del todo seguro, tal vez fue cin.get) así que getline acaba de delimitar el momento en que se une al buffer de entrada cuando encuentra el sobrante '\ n'. –

Cuestiones relacionadas