Pregunta

Cuando uso getline, lo haría de entrada un montón de cadenas o números, pero sólo quiere que el bucle while para dar salida a la "palabra" si no es un número. Entonces, ¿hay alguna manera de comprobar si "palabra" es un número o no? Sé que podría utilizar para atoi() C-cuerdas pero ¿qué hay de cuerdas de la clase string?

int main () {
  stringstream ss (stringstream::in | stringstream::out);
  string word;
  string str;
  getline(cin,str);
  ss<<str;
  while(ss>>word)
    {
      //if(    )
        cout<<word<<endl;
    }
}
¿Fue útil?

Solución

Otra versión ...

strtol , envolviéndolo dentro de una función sencilla de ocultar su complejidad:

inline bool isInteger(const std::string & s)
{
   if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;

   char * p;
   strtol(s.c_str(), &p, 10);

   return (*p == 0);
}

¿Por qué strtol?

Por lo que yo quiero C ++, a veces la API C es la mejor respuesta en lo que a mí respecta:

  • el uso de excepciones es demasiado para una prueba de que está autorizada a fallar
  • la creación de objeto de secuencia temporal por el elenco léxica es una exageración y el exceso de ineficientes cuando la biblioteca estándar de C tiene una función dedicada poco conocido que hace el trabajo.

¿Cómo funciona?

strtol parece bastante cruda, a primera vista, por lo que una explicación hará que el código más fácil de leer:

strtol será analizar la cadena, con parada en el primer carácter que no puede ser considerada como parte de un entero. Si usted proporciona p (como lo hice anteriormente), se establece p justo en este primer carácter no entero.

Mi razonamiento es que si p no se establece hasta el final de la cadena (el carácter 0), entonces hay un carácter no entero en el s cadena, lo que significa s no es un número entero correcta.

Las primeras pruebas están ahí para eliminar casos de esquina (espacios principales, cadena vacía, etc.).

Esta función debe ser, por supuesto, adaptados a sus necesidades (son los principales espacios de un error? Etc.).

Fuentes:

Vea la descripción de strtol en: http: //en.cppreference. com / w / CPP / cadena / bytes / strtol .

Ver, también, la descripción de las funciones de la hermana de strtol (strtod, strtoul, etc.).

Otros consejos

La respuesta aceptado, le dan un falso positivo si la entrada es un número más el texto, porque "STOL" convertirá los dígitos PRIMEROS e ignorar el resto.

I como la versión siguiente a la mayoría, ya que es un bonito de una sola línea que no necesita definir una función y sólo se puede copiar y pegar donde lo necesite.

#include <string>

...

std::string s;

bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);

EDIT: si te gusta esta aplicación sino que usted desea utilizarlo como una función, entonces esto debe hacer:

bool has_only_digits(const string s){
  return s.find_first_not_of( "0123456789" ) == string::npos;
}

Usted puede tratar de boost::lexical_cast. Se produce una excepción bad_lexical_cast si falla.

En su caso:

int number;
try
{
  number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
  std::cout << word << "isn't a number" << std::endl;
}

Si sólo está mirando si word es un número, que no es demasiado difícil:

#include <ctype.h>

...

string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
    isNumber &&= isdigit(*k);

Optimizar como se desee.

Puede utilizar boost::lexical_cast, como se sugiere, pero si usted tiene ningún conocimiento previo sobre las cuerdas (es decir, que si una cadena contiene un literal entero no tendrá ningún espacio inicial, o que los enteros no se escriben con exponentes), luego rodar su propia función debe ser a la vez más eficiente, y no es particularmente difícil.

Utilice los todopoderosos C stdio / funciones de cadena:

int dummy_int;
int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int);

if (scan_value == 0)
    // does not start with integer
else
    // starts with integer

Bien, la forma en que veo que usted tiene 3 opciones.

1: Si simplemente desea comprobar si el número es un entero, y no se preocupan por su conversión, sino que simplemente desea mantenerlo como una cadena y no se preocupan por los desbordamientos potenciales, comprobar si coincide con una regex para un entero sería ideal aquí.

2: Puede utilizar impulso :: lexical_cast y luego coger un potencial impulso :: excepción bad_lexical_cast para ver si la conversión no. Esto funcionaría bien si se puede usar impulso y si no la conversión es una condición excepcional.

3: rodar su propia función similar a lexical_cast que los controles de la conversión y vuelve verdadero / falso dependiendo de si tiene éxito o no. Esto funcionaría en el caso 1 y 2 no se ajusta a sus necesidades.

template <typename T>
const T to(const string& sval)
{
        T val;
        stringstream ss;
        ss << sval;
        ss >> val;
        if(ss.fail())
                throw runtime_error((string)typeid(T).name() + " type wanted: " + sval);
        return val;
}

Y a continuación, se puede usar así:

double d = to<double>("4.3");

o

int i = to<int>("4123");

He modificado de paercebal método para satisfacer mis necesidades:

typedef std::string String;    

bool isInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0])) return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isPositiveInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isNegativeInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}

Nota:

  1. Puede comprobar si hay varias bases (binario, oct, hexagonal y otros)
  2. make seguro usted no pasa 1, valor negativo o el valor >36 como base.
  3. Si pasa 0 como la base, detectará el auto es decir la base para una cadena que comienza con 0x será tratado como hexagonal y la cadena que comienza con 0 será tratado como oct. Los personajes son mayúsculas y minúsculas.
  4. Cualquier espacio en blanco en la cadena hará que sea return false.

Aquí hay otra solución.

try
{
  (void) std::stoi(myString); //cast to void to ignore the return value   
  //Success! myString contained an integer
} 
catch (const std::logic_error &e)
{   
  //Failure! myString did not contain an integer
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top