He tenido problemas para escribir una función que verifique si una cadena es un número. Para un juego que estoy escribiendo, solo necesito verificar si una línea del archivo que estoy leyendo es un número o no (sabré si es un parámetro de esta manera). Escribí la siguiente función que creo que estaba funcionando sin problemas (o la edité accidentalmente para detenerla o soy esquizofrénico o Windows es esquizofrénico):
bool isParam (string line)
{
if (isdigit(atoi(line.c_str())))
return true;
return false;
}
c++
visual-c++
Brendan Weinstein
fuente
fuente
if (expr) return true; return false;
! Solo escribereturn expr;
.if (expr) return expr; else return expr;
,if (expr == true)
,(if expr != false)
, oif ((expr == true) == true)
. Todos introducen una complejidad que no beneficia al escritor, lector o compilador del código. La eliminación de la complejidad innecesaria no es un atajo; Es clave para escribir un mejor software.Respuestas:
La forma más eficiente sería simplemente iterar sobre la cadena hasta que encuentre un carácter que no sea un dígito. Si hay caracteres que no sean dígitos, puede considerar que la cadena no es un número.
O si quieres hacerlo de la manera C ++ 11:
Como se señala en los comentarios a continuación, esto solo funciona para enteros positivos. Si necesita detectar enteros negativos o fracciones, debe optar por una solución más sólida basada en la biblioteca. Sin embargo, agregar soporte para enteros negativos es bastante trivial.
fuente
!s.empty() && s.find_first_not_of("0123456789") == std::string::npos;
para una línea única C ++ 03.int
. Solo identifica si una cadena está compuesta de dígitos numéricos. No importa la longitud de la cadena.<string>
<algorithm>
y<cctype>
hacer que el ejemplo de C ++ 11 funcione.¿Por qué reinventar la rueda? La biblioteca estándar de C (disponible también en C ++) tiene una función que hace exactamente esto:
Si desea manejar fracciones o notación científica, elija en su
strtod
lugar (obtendrá undouble
resultado).Si desea permitir constantes hexadecimales y octales en estilo C / C ++ (
"0xABC"
), haga el último parámetro en su0
lugar.Su función entonces puede escribirse como
fuente
atoi
como se usa en la pregunta, también lo hace).p
se establecerá ennullptr
sistrtol
tiene éxito, ¿verdad? Eso no es lo que estoy viendo :(p
apuntará a la NUL que termina la cadena. Asíp != 0
y*p == 0
.Con el compilador C ++ 11, para enteros no negativos, usaría algo como esto (tenga
::
en cuenta el en lugar destd::
):http://ideone.com/OjVJWh
fuente
Puede hacerlo de la manera C ++ con boost :: lexical_cast. Si realmente insiste en no usar el impulso, simplemente puede examinar lo que hace y hacerlo. Es muy simple
fuente
try{} catch{}
una buena idea? ¿No deberíamos evitarlo tanto como sea posible?Solo quería incluir esta idea que usa iteración, pero algún otro código hace esa iteración:
No es robusto como debería ser cuando se busca un punto decimal o un signo menos, ya que permite que haya más de uno de cada uno y en cualquier ubicación. Lo bueno es que es una sola línea de código y no requiere una biblioteca de terceros.
Saca '.' y '-' si los enteros positivos son todo lo que está permitido.
fuente
std::string
, use sufind_first_not_of
función miembro.Sugeriría un enfoque regex. Una coincidencia completa de expresiones regulares (por ejemplo, usando boost :: regex ) con
mostraría si la cadena es un número o no. Esto incluye números positivos y negativos, enteros y decimales.
Otras variaciones
(solo positivo)
(solo entero)
(solo entero positivo)
fuente
std::regex
con gcc 4.7, gcc 4.8: ambos arrojanstd::regex_error
cualquier signo de[
regexp, incluso para un inocente "[abc]" (¿lo hago mal?). clang-3.4 no tiene conocimiento de<regex>
nada. De todos modos, esta parece ser la respuesta más sensata, +1.Aquí hay otra forma de hacerlo usando la
<regex>
biblioteca:fuente
Con esta solución, puede verificar todo, desde números negativos a positivos e incluso números flotantes. Cuando cambia el tipo de
num
entero, obtendrá un error si la cadena contiene un punto.Probar: Programa C ++
fuente
He encontrado que el siguiente código es el más robusto (c ++ 11). Atrapa tanto enteros como flotadores.
fuente
using namespace std;
es innecesaria.Aquí hay una solución para verificar enteros positivos:
fuente
Prueba esto:
fuente
Brendan esto
está casi bien
suponiendo que cualquier cadena que comience con 0 es un número, simplemente agregue un cheque para este caso
ofc "123hello" volverá verdadero como Tony D señaló.
fuente
Lo más simple que se me ocurre en c ++
Ejemplo de código de trabajo: https://ideone.com/nRX51Y
fuente
Mi solución usando C ++ 11 regex (
#include <regex>
), se puede usar para una verificación más precisa, comounsigned int
,double
etc.Puede encontrar este código en http://ideone.com/lyDtfi , que puede modificarse fácilmente para cumplir con los requisitos.
fuente
Una solución basada en un comentario de kbjorklu es:
Al igual que con la respuesta de David Rector, no es robusto para las cadenas con múltiples puntos o signos menos, pero puede eliminar esos caracteres para verificar los enteros.
Sin embargo, soy parcial a una solución, basada en la solución de Ben Voigt , que usa
strtod
en cstdlib para buscar valores decimales, notación científica / de ingeniería, notación hexadecimal (C ++ 11), o incluso INF / INFINITY / NAN (C ++ 11) es:fuente
Podemos usar una clase stringstream .
fuente
Utilizando
<regex>
. Este código fue probado!fuente
Después de consultar un poco más la documentación, se me ocurrió una respuesta que respalda mis necesidades, pero que probablemente no será tan útil para otros. Aquí está (sin el molesto return true y return false declaraciones :-))
fuente
0
, obtendrás un falso negativo.Creo que esta expresión regular debería manejar casi todos los casos
para que pueda probar la siguiente función que puede funcionar con ambos (Unicode y ANSI)
fuente
Para validar dobles:
}
Para validar Ints (con negativos)
}
Para validar Ints sin firmar
}
fuente
cómo funciona: la sobrecarga de secuencia de cadena >> puede convertir cadenas a varios tipos aritméticos, lo hace leyendo caracteres secuencialmente de la secuencia de secuencia (ss en este caso) hasta que se queda sin caracteres O el siguiente carácter no cumple los criterios para ser almacenado en el tipo de variable de destino.
Ejemplo 1:
ejemplo2:
ejemplo3:
la explicación variable "basura":
¿por qué no simplemente verificar si la extracción en mi doble tiene un valor válido y luego devolver verdadero si lo tiene?
observe que el ejemplo 3 anterior aún leerá con éxito el número 11 en la variable my_number incluso si la cadena de entrada es "11ABCD" (que no es un número).
Para manejar este caso, podemos hacer otra extracción en una variable de cadena (que denominé basura) que puede leer cualquier cosa que pueda haber quedado en el búfer de cadena después de la extracción inicial en la variable de tipo double. Si queda algo, se leerá en "basura", lo que significa que la cadena completa que se pasó no era un número (solo comienza con uno). en este caso, nos gustaría devolver falso;
la explicación "0" antepuesta:
intentar extraer un solo carácter en un doble fallará (devolver 0 en nuestro doble) pero aún moverá la posición del búfer de cadena a después del carácter. En este caso, nuestra lectura de basura estará vacía, lo que provocaría que la función devuelva incorrectamente verdadero. para evitar esto, agregué un 0 a la cadena de modo que si, por ejemplo, la cadena que se ingresó fuera "a", se cambia a "0a" para que el 0 se extraiga en el doble y "a" se extraiga en la basura.
anteponer un 0 no afectará el valor del número, por lo que el número aún se extraerá correctamente en nuestra variable doble.
fuente
para verificar si una cadena es un número entero o un punto flotante o podría usar:
fuente
Otra respuesta más, que usa
stold
(aunque también podría usarstof
/stod
si no requiere la precisión).fuente
Como se me reveló en una respuesta a mi pregunta relacionada, creo que debería usar boost :: conversion :: try_lexical_convert
fuente
Prueba esto:
fuente
Puede probar si una cadena es convertible a entero utilizando boost :: lexical_cast . Si arroja una excepción bad_lexical_cast, entonces la cadena no se podría convertir, de lo contrario, puede.
Vea el ejemplo de dicho programa de prueba a continuación:
Ejecución de muestra:
fuente
Hace unos meses, implementé una forma de determinar si alguna cadena es entera, hexadecimal o doble.
Luego, en su programa, puede convertir fácilmente el número en función de su tipo si hace lo siguiente,
Puede darse cuenta de que la función devolverá un 0 si no se detectó el número. El 0 se puede tratar como falso (como booleano).
fuente
Propongo una convención simple:
Si la conversión a ASCII es> 0 o comienza con 0, entonces es un número. No es perfecto sino rápido.
Algo como esto:
fuente
Esta función se ocupa de todos los casos posibles:
fuente
¿Podría simplemente usar el código de retorno de sscanf para determinar si es un int?
fuente