2010-12-14 8 views
54

Duplicar posibles:
How to parse a string to an int in C++?C++ de análisis int de cadena

he hecho un poco de investigación y algunas personas dicen utilizar ación y otros dicen que es malo, y no puedo conseguir para que funcione de todos modos.

Así que solo quiero preguntar a toda máquina, ¿cuál es la forma correcta de convertir una cadena a un int.

string s = "10"; 
int i = s....? 

¡Gracias!

+3

es probable que quiso decir ('std ::') 'string s =" 10 "'. – lijie

+1

Duplicado de http://stackoverflow.com/questions/200090/how-do-you-convert-ac-string-to-an-int y http://stackoverflow.com/questions/194465/how-to-parse -a-string-to-an-int-in-c –

+0

@lijie - tal vez, pero nunca digo eso en mi código ... ¿debería estarlo? – kralco626

Respuesta

64
  • En C++ 11, utilice std::stoi como:

    std::string s = "10"; 
    int i = std::stoi(s); 
    

    Nota que std::stoi arrojará excepción de tipo std::invalid_argument si la conversión no se puede realizar, o std::out_of_range si los resultados de la conversión en desbordamiento (es decir, cuando el valor de la cadena es demasiado grande para el tipo int). Puede usar std::stol o std:stoll, aunque en el caso int parece demasiado pequeño para la cadena de entrada.

  • En C++ 03/98, cualquiera de los siguientes puede usarse:

    std::string s = "10"; 
    int i; 
    
    //approach one 
    std::istringstream(s) >> i; //i is 10 after this 
    
    //approach two 
    sscanf(s.c_str(), "%d", &i); //i is 10 after this 
    

Nota que los dos enfoques anteriores fallarían para la entrada s = "10jh". Devolverán 10 en lugar de notificar el error. Por lo tanto, el enfoque seguro y robusto es escribir su propia función que analiza la cadena de entrada y verificar que cada carácter verifique si es un dígito o no, y luego trabaje en consecuencia. Aquí es uno implemtation robusto (no probado aunque): versión

int to_int(char const *s) 
{ 
    if (s == NULL || *s == '\0') 
     throw std::invalid_argument("null or empty string argument"); 

    bool negate = (s[0] == '-'); 
     if (*s == '+' || *s == '-')  
        ++s; 

    if (*s == '\0') 
     throw std::invalid_argument("sign character only."); 

     int result = 0; 
     while(*s) 
     { 
          if (*s >= '0' && *s <= '9') 
          { 
              result = result * 10  - (*s - '0');  //assume negative number 
          } 
          else 
              throw std::invalid_argument("invalid input string"); 
          ++s; 
     } 
     return negate ? result : -result; //-result is positive! 
}  

Esta solución se modifica ligeramente de my another solution.

+4

En general, evitaría 'atoi' en la entrada proporcionada por el usuario, ya que, cuando obtienes un 0, no sabes si es porque la cadena contenía '" 0 "' o porque no era válida. –

+0

Atoi y itoa a menudo causan problemas, así que recomendaría evitar estas funciones. Yo usaría boost o stringstream en su lugar. – RageD

+0

bueno para un proyecto rápido, aunque debido a su simplicidad – kralco626

7

Puede usar istringstream.

string s = "10"; 

// create an input stream with your string. 
istringstream is(str); 

int i; 
// use is like an input stream 
is >> i; 
12

Puede utilizar boost::lexical_cast:

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

int main(int argc, char* argv[]){ 
std::string s1 = "10"; 
std::string s2 = "abc"; 
int i; 

    try { 
     i = boost::lexical_cast<int>(s1); 
    } 
    catch(boost::bad_lexical_cast & e){ 
     std::cout << "Exception caught : " << e.what() << std::endl; 
    } 

    try { 
     i = boost::lexical_cast<int>(s2); 
    } 
    catch(boost::bad_lexical_cast & e){ 
     std::cout << "Exception caught : " << e.what() << std::endl; 
    } 

    return 0; 
} 
+9

boost lexical_cast es muy muy muy lento también el hecho de que requiere manejo de excepciones lo hace aún más difícil de usar. solo es bueno para la entrada que entra a velocidades de usuario, nada más. –

+0

@dman: de hecho, lexical_cast es más lento que atoi/strtol/sscanf, pero 1) el OP no preguntó sobre la forma más rápida (y la pregunta está etiquetada C++) 2) lexical_cast es una solución genérica y ser parte de Boost puede decirle algunas cosas sobre la calidad de la implementación 3) la excepción bad_lexical_cast le proporciona una forma de detectar errores de conversión, un pequeño precio a pagar por el manejo correcto de errores 4) si lexical_cast su cuello de botella es bastante fácil implementar una especialización para sus tipos de datos –

+0

+1 en este . Me gusta tu argumento, y realmente me gusta la solución. Como soy una persona de Java, me gusta intentar capturar y probablemente usaré esta solución en el futuro. – kralco626

9

No hay manera "correcta". Si quieres una solución universal (pero no óptima), puedes usar un impulso :: elenco léxico.

Una solución común para C++ es utilizar el operador std :: ostream y < <. Puede usar un método stringstream y stringstream :: str() para la conversión a cadena.

Si realmente necesita un mecanismo rápido (recuerde la regla 20/80) se puede buscar una solución "dedicado" como http://www.partow.net/programming/strtk/index.html

Best Regards,
Marcin

+19

"No hay una 'buena manera'" - tienes que amar un idioma donde no hay una "forma correcta" de analizar una cadena ...:( – kralco626

4

Algunas funciones rápidas a mano (si no se está usando Boost):

template<typename T> 
std::string ToString(const T& v) 
{ 
    std::ostringstream ss; 
    ss << v; 
    return ss.str(); 
} 

template<typename T> 
T FromString(const std::string& str) 
{ 
    std::istringstream ss(str); 
    T ret; 
    ss >> ret; 
    return ret; 
} 

Ejemplo:

int i = FromString<int>(s); 
std::string str = ToString(i); 

Funciona para cualquier tipo de transmisiones (flotadores, etc.). Necesitarás #include <sstream> y posiblemente también #include <string>.

+2

Este es el boost de la solución :: lexical_cast usa – Marcin

+0

Actualla boost :: lexical_cast no usa las cadenas std originales, sino una clase de flujo ajustado que debería hacer que sea un poco más rápido que estas funciones. También incluye error- comprobación (incluida la verificación si la entrada fue consumida por el operador de extracción), por lo que es mucho más seguro de usar que esas dos funciones. –