2011-02-07 18 views
8

Aparentemente, se supone que esto funciona para mostrar si una cadena es numérica, por ejemplo "12.5" == sí, "abc" == no. Sin embargo, recibo una respuesta no despreciable.¿Puedo decir si std :: string representa un número usando stringstream?

std::stringstream ss("2"); 
double d; ss >> d; 
if(ss.good()) {std::cout<<"number"<<std::endl;} 
else {std::cout<<"other"<<std::endl;} 
+2

significa "12,5 abc" califican como "una cadena es numérico"? Si es "no", ninguna de las respuestas se aplica hasta el momento. – etarion

Respuesta

4

debe utilizar un istringstream para que sepa que está tratando de analizar la entrada. Además, simplemente verifique el resultado de la extracción directamente en lugar de usar good más adelante.

#include <sstream> 
#include <iostream> 

int main() 
{ 
    std::istringstream ss("2"); 
    double d = 0.0; 
    if(ss >> d) {std::cout<<"number"<<std::endl;} 
    else {std::cout<<"other"<<std::endl;} 
} 
+0

¿Cómo funciona "él sabe que está tratando de analizar la entrada" en absoluto? Quizás sea bueno para la claridad del código, pero no veo ninguna razón técnica. –

+1

No está buscando contenido adicional. "2 abc" no es un número, por ejemplo, es una cadena con espacios en blanco incrustados.IIRC, la solución es verificar {{ss.peek() == EOF}} (todo fue consumido) o tal vez mirando {{ss.gcount()}}. – Tom

7

No utilizar bueno()! Comprueba si la corriente es failed or not:

if (ss) 

Bueno le indica si cualquiera de eofbit, badbit o failbit está ajustada, mientras que fallar() le informa sobre badbit y failbit. Casi nunca se preocupa por eofbit a menos que ya sea sepa que la transmisión ha fallado, por lo que casi nunca desea utilizarla.

Tenga en cuenta que las pruebas de la corriente directa, como el anterior, es exactamente equivalente a:

if (!ss.fail()) 

Por el contrario, ss es equivalente a ss.fail().


La combinación de la extracción en la expresión condicional:

if (ss >> d) {/*...*/} 

es exactamente equivalente a:

ss >> d; 
if (ss) {/*...*/} 

Sin embargo, es probable que desee probar si la cadena completa puede ser convertido a un doble, que es un poco más complicado. Use boost :: lexical_cast que ya maneja todos los casos.

-1
int str2int (const string &str) { 
    stringstream ss(str); 
    int num; 
    if((ss >> num).fail()) 
    { 
     //ERROR: not a number 
    } 
    return num; 
} 
5

Si desea comprobar si un string contiene única un número y nada más (excepto en los espacios en blanco), utilice la siguiente:

#include <sstream> 

bool is_numeric (const std::string& str) { 
    std::istringstream ss(str); 
    double dbl; 
    ss >> dbl;  // try to read the number 
    ss >> std::ws; // eat whitespace after number 

    if (!ss.fail() && ss.eof()) { 
     return true; // is-a-number 
    } else { 
     return false; // not-a-number 
    } 
} 

El ss >> std::ws es importante para la aceptación de números con espacios en blanco de tales como "24 ".

La comprobación ss.eof() es importante para rechazar cadenas como "24 abc". Asegura que alcanzamos el final de la cadena después de leer el número (y el espacio en blanco).

prueba arnés:

#include <iostream> 
#include <iomanip> 

int main() 
{ 
    std::string tests[8] = { 
      "", "XYZ", "a26", "3.3a", "42 a", "764", " 132.0", "930 " 
    }; 
    std::string is_a[2] = { "not a number", "is a number" }; 
    for (size_t i = 0; i < sizeof(tests)/sizeof(std::string); ++i) { 
     std::cout << std::setw(8) << "'" + tests[i] + "'" << ": "; 
     std::cout << is_a [is_numeric (tests[i])] << std::endl; 
    } 
} 

Salida:

 '': not a number 
    'XYZ': not a number 
    'a26': not a number 
    '3.3a': not a number 
    '42 a': not a number 
    '764': is a number 
' 132.0': is a number 
    '930 ': is a number 
Cuestiones relacionadas