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

Resuelto Brendan Weinstein asked hace 13 años • 40 respuestas

He tenido bastantes problemas al intentar 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 (de esta manera sabré si es un parámetro). Escribí la siguiente función que creo que funcionaba 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 avatar Jan 11 '11 12:01 Brendan Weinstein
Aceptado

La forma más eficiente sería simplemente iterar sobre la cadena hasta encontrar un carácter que no sea un dígito. Si hay caracteres que no sean dígitos, puede considerar la cadena, no 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 a 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 sólo funciona para números enteros positivos. Si necesita detectar números enteros o fracciones negativos, debe optar por una solución basada en biblioteca más sólida. Aunque agregar soporte para números enteros negativos es bastante trivial.

Charles Salvia avatar Jan 11 '2011 06:01 Charles Salvia

¿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, opte por strtodesta (obtendrá un doubleresultado).

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

Su función entonces se puede escribir como

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Ben Voigt avatar May 15 '2013 21:05 Ben Voigt

Con el compilador C++11, para enteros no negativos usaría algo como esto (tenga en cuenta 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 avatar Jul 31 '2013 16:07 szx