¿Cómo puedo comprobar si una cadena C ++ es un int?
-
27-09-2019 - |
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;
}
}
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:
- Puede comprobar si hay varias bases (binario, oct, hexagonal y otros)
- make seguro usted no pasa
1
, valor negativo o el valor>36
como base. - Si pasa
0
como la base, detectará el auto es decir la base para una cadena que comienza con0x
será tratado como hexagonal y la cadena que comienza con0
será tratado como oct. Los personajes son mayúsculas y minúsculas. - 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
}