¿Cómo determinar si una cadena es un número con C ++?

136

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;
}
Brendan Weinstein
fuente
184
¡ Odio ver if (expr) return true; return false;! Solo escribe return expr;.
Ephemient
17
@ephemient Mi estilo es hacer lo mismo que tú. ¿Pero es realmente un gran problema?
Brennan Vincent el
2
Su prototipo de función no parece apropiado. ¿Por qué no utilizar bool isParam (const string & line)
MikimotoH
44
Si. Tengo la mala costumbre de codificar a largo plazo cuando aprendo un nuevo idioma. Soy nuevo en C ++ y tengo más dudas sobre los "atajos" (o los atajos percibidos).
Brendan Weinstein
57
@Brennan Vincent: Sí, es un gran problema. Es la misma clase de errores como if (expr) return expr; else return expr;, if (expr == true), (if expr != false), o if ((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.
MSalters

Respuestas:

148

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.

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

O si quieres hacerlo de la manera C ++ 11:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

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.

Charles Salvia
fuente
66
Tampoco maneja números negativos y números no enteros. No podemos saber cuáles son los requisitos en función de la pregunta.
Brennan Vincent
76
También podría usarlo !s.empty() && s.find_first_not_of("0123456789") == std::string::npos;para una línea única C ++ 03.
kbjorklu
8
Tampoco maneja números decimales, por ejemplo: 1.23
littlecodefarmer758
3
@Remy Lebeau, sí. En realidad, no está convirtiendo la cadena en un int. Solo identifica si una cadena está compuesta de dígitos numéricos. No importa la longitud de la cadena.
Charles Salvia
55
No olvide incluir <string> <algorithm>y <cctype>hacer que el ejemplo de C ++ 11 funcione.
kR105
88

¿Por qué reinventar la rueda? La biblioteca estándar de C (disponible también en C ++) tiene una función que hace exactamente esto:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

Si desea manejar fracciones o notación científica, elija en su strtodlugar (obtendrá un doubleresultado).

Si desea permitir constantes hexadecimales y octales en estilo C / C ++ ( "0xABC"), haga el último parámetro en su 0lugar.

Su función entonces puede escribirse como

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Ben Voigt
fuente
44
Esta función descarta el espacio en blanco al frente. Por lo tanto, debe verificar el primer carácter de isdigit.
Chmike
1
@chmike: Según mi comprensión de la pregunta, descartar el espacio en blanco inicial es el comportamiento correcto ( atoicomo se usa en la pregunta, también lo hace).
Ben Voigt
1
La pregunta no lo especificó explícitamente, pero mi comprensión del requisito "comprueba si una cadena es un número" significa que toda la cadena es el número, por lo tanto, no hay espacios. Sentí la necesidad de señalar que su respuesta es diferente a las demás a este respecto. Su respuesta puede estar bien si está bien que la cadena tenga espacios delante del número.
chmike 01 de
1
@BenVoigt Estás diciendo que pse establecerá en nullptrsi strtoltiene éxito, ¿verdad? Eso no es lo que estoy viendo :(
Jonathan Mee
2
@ JonathanMee: No, papuntará a la NUL que termina la cadena. Así p != 0y *p == 0.
Ben Voigt
33

Con el compilador C ++ 11, para enteros no negativos, usaría algo como esto (tenga ::en cuenta el en lugar de std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh

szx
fuente
1
Esta es la mejor respuesta.
Martin Broadhurst
Si hay caracteres utf8 en la cadena, obtendrá un error de tiempo de ejecución.
Rey León
29

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

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
Edward extraño
fuente
21
¿Usando try{} catch{}una buena idea? ¿No deberíamos evitarlo tanto como sea posible?
Nawaz
32
-1 por abuso intente captura ... blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
NoSenseEtAl
14
intente {} catch {} es apropiado aquí. Sin embargo, atrapar (...) es solo una mala práctica. En este caso, use boost :: bad_lexical_cast para su controlador de excepciones.
NuSkooler
55
Siento que esto está tratando de leer de un archivo. No importa cuánto compruebe en el archivo, no sabrá si es posible leerlo hasta que lo haga. O va a funcionar o no. En cuyo caso tendrá que atrapar una excepción. Entonces, en este caso, creo que esta es una forma completamente buena de hacerlo.
Casey
44
@EarlGray: ciertamente me interesaría saber qué acciones dependientes del sistema operativo tomarían Windows El estándar es bastante claro sobre cómo debe comportarse este código.
Edward Strange
16

Solo quería incluir esta idea que usa iteración, pero algún otro código hace esa iteración:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

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.

David Rector
fuente
error: 'strspn' no se declaró en este ámbito, creo que esto se debe a que me falta un "#include", pero cuál
Qwertie
44
Si va a usar std::string, use su find_first_not_offunción miembro.
Ben Voigt
55
Esto fallaría si pasa una cadena de "12.3-4.55-", que obviamente no es un número válido
Buzzrick
Buzzrick, la respuesta propuesta ya indica que esto fallaría con el no número que mencionó.
David Rector
si lo limita solo a "0123456789", entonces la fórmula es perfecta para probar un entero sin signo
nadie especial
16

Sugeriría un enfoque regex. Una coincidencia completa de expresiones regulares (por ejemplo, usando boost :: regex ) con

-?[0-9]+([\.][0-9]+)?

mostraría si la cadena es un número o no. Esto incluye números positivos y negativos, enteros y decimales.

Otras variaciones

[0-9]+([\.][0-9]+)?

(solo positivo)

-?[0-9]+

(solo entero)

[0-9]+

(solo entero positivo)

Mephane
fuente
Ejem, traté de usar std::regexcon gcc 4.7, gcc 4.8: ambos arrojan std::regex_errorcualquier 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.
Dmytro Sirenko
3
@EarlGray: Regex solo está disponible correctamente desde GCC 4.9
Carreras de ligereza en órbita
13

Aquí hay otra forma de hacerlo usando la <regex>biblioteca:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
mpataki14
fuente
Ah, así sería. He actualizado con una mejor solución. Gracias.
mpataki14
¿No debería ser "[(- | +) |] [0-9] +" (más en lugar de una estrella), de lo contrario, su expresión regular podría coincidir en "-" o "+" como un número válido.
David Mulder
Agradable. No estoy seguro de lo que están haciendo (, | y) en esa primera clase de caracteres: por lo que yo sé, esos metacaracteres pierden su significado especial dentro de una clase de caracteres. ¿Qué tal "^ [- +]? [0-9] + $"?
U007D
Puede ser ineficiente. Cada vez que se llama, llama al constructor std :: regex que compila la expresión regular.
user31264
12

Con esta solución, puede verificar todo, desde números negativos a positivos e incluso números flotantes. Cuando cambia el tipo de numentero, obtendrá un error si la cadena contiene un punto.

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

Probar: Programa C ++

tzwickl
fuente
10

He encontrado que el siguiente código es el más robusto (c ++ 11). Atrapa tanto enteros como flotadores.

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
dk123
fuente
Parece que la línea using namespace std;es innecesaria.
Xam
5

Aquí hay una solución para verificar enteros positivos:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}
Jaime Soto
fuente
5

Prueba esto:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Tomász
fuente
1
Esto prueba solo para enteros sin signo
nadie especial
4

Brendan esto

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

está casi bien

suponiendo que cualquier cadena que comience con 0 es un número, simplemente agregue un cheque para este caso

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}

ofc "123hello" volverá verdadero como Tony D señaló.

Noam Geffen
fuente
3

Lo más simple que se me ocurre en c ++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
        if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

Ejemplo de código de trabajo: https://ideone.com/nRX51Y

Abhijit Annaldas
fuente
3

Mi solución usando C ++ 11 regex ( #include <regex>), se puede usar para una verificación más precisa, como unsigned int, doubleetc.

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

Puede encontrar este código en http://ideone.com/lyDtfi , que puede modificarse fácilmente para cumplir con los requisitos.

aniliitb10
fuente
Solicitaría a los downvoters que me ayudaran a entender el problema, mejoraré mi respuesta. Gracias.
aniliitb10
2

Una solución basada en un comentario de kbjorklu es:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

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 strtoden 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:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}
revs chappjc
fuente
2

Podemos usar una clase stringstream .

    bool isNumeric(string str)
    {
       stringstream stream;                   
       double number;

       stream<<str;
       stream>>number;

       return stream.eof();
    }
rashedcs
fuente
2

Utilizando <regex>. Este código fue probado!

bool isNumber(const std::string &token)
{
    return std::regex_match(token, std::regex("(\\+|-)?[0-9]*(\\.?([0-9]+))$"));
}
Nery Jr
fuente
1

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 :-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}
Brendan Weinstein
fuente
44
Si el número es 0, obtendrás un falso negativo.
Charles Salvia
3
Esto devolverá cualquier número inicial, y no le advertirá de basura final (por ejemplo, "123hello" ==> 123). @Charles: Brendan menciona que solo necesita reconocer entradas positivas en un comentario sobre otra respuesta.
Tony Delroy
1

Creo que esta expresión regular debería manejar casi todos los casos

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

para que pueda probar la siguiente función que puede funcionar con ambos (Unicode y ANSI)

bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
    std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}
Motaz
fuente
1
include <string>

Para validar dobles:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
    return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
    return false;
return true;

}

Para validar Ints (con negativos)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
    return false;
else if (1 < negativeSigns) // More than 1 negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
    return false;
return true;

}

Para validar Ints sin firmar

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}

Erik Nordin
fuente
1
bool isNumeric(string s){
    if ( !s.empty() && s[0] != '-' )
        s = "0" + s; //prepend 0

    string garbage;

    stringstream ss(s); 
    ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
    //if there is no garbage return true or else return false
    return garbage.empty(); 
}

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:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

ejemplo2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

ejemplo3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

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.

KorreyD
fuente
1
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a por qué y / o cómo responde la pregunta mejora su valor a largo plazo.
Ajean
1

para verificar si una cadena es un número entero o un punto flotante o podría usar:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}
MuhammadKhalifa
fuente
1
esto devolverá 10 para una cadena que contiene el valor "10_is_not_a_number".
KorreyD
1

Otra respuesta más, que usa stold(aunque también podría usar stof/ stodsi no requiere la precisión).

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}
Tim Angus
fuente
1

Prueba esto:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}
rrlinus
fuente
1

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:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

Ejecución de muestra:

# ./a.out 12
12 YES
# ./a.out 12/3
NO
Łukasz Ślusarczyk
fuente
0

Hace unos meses, implementé una forma de determinar si alguna cadena es entera, hexadecimal o doble.

enum{
        STRING_IS_INVALID_NUMBER=0,
        STRING_IS_HEXA,
        STRING_IS_INT,
        STRING_IS_DOUBLE
};

bool isDigit(char c){
    return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
    return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

    while(CString::isDigit(*aux_p)) aux_p++;
    return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

    while(CString::isHexaDigit(*aux_p)) aux_p++;
    return aux_p;
}


int isNumber(const string & test_str_number){
    bool isHexa=false;
    char *str = (char *)test_str_number.c_str();

    switch(*str){
    case '-': str++; // is negative number ...
               break;
    case '0': 
              if(tolower(*str+1)=='x')  {
                  isHexa = true;
                  str+=2;
              }
              break;
    default:
            break;
    };

    char *start_str = str; // saves start position...
    if(isHexa) { // candidate to hexa ...
        str = ADVANCE_HEXADIGITS(str);
        if(str == start_str)
            return STRING_IS_INVALID_NUMBER;

        if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

    }else{ // test if integer or float
        str = ADVANCE_DIGITS(str);
        if(*str=='.') { // is candidate to double
            str++;
            str = ADVANCE_DIGITS(str);
            if(*str == ' ' || *str == 0)
                return STRING_IS_DOUBLE;

            return STRING_IS_INVALID_NUMBER;
        }

        if(*str == ' ' || *str == 0)
            return STRING_IS_INT;

    }

    return STRING_IS_INVALID_NUMBER;


}

Luego, en su programa, puede convertir fácilmente el número en función de su tipo si hace lo siguiente,

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

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).

Jordi Espada
fuente
0

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:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}
Gokhan Unel
fuente
0

Esta función se ocupa de todos los casos posibles:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}
Vaibhav Gupta
fuente
0

¿Podría simplemente usar el código de retorno de sscanf para determinar si es un int?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}
David D
fuente