Estoy tratando de convertirme std::stringa float/double. Lo intenté:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Pero siempre devuelve cero. ¿Alguna otra forma?
Estoy tratando de convertirme std::stringa float/double. Lo intenté:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Pero siempre devuelve cero. ¿Alguna otra forma?
Respuestas:
std::string num = "0.6";
double temp = ::atof(num.c_str());
Lo hace por mí, es una sintaxis válida de C ++ para convertir una cadena en un doble.
Puede hacerlo con stringstream o boost :: lexical_cast, pero esos vienen con una penalización de rendimiento.
Ahaha tienes un proyecto Qt ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Nota adicional:
si los datos de entrada son a const char*, QByteArray::toDoubleserá más rápido.
La biblioteca estándar (C ++ 11) ofrece la funcionalidad deseada con std::stod:
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
Generalmente para la mayoría de los otros tipos básicos, consulte <string>. También hay algunas características nuevas para las cuerdas C. Ver<stdlib.h>
ostringstreamen sí era simplemente demasiado tiempo para escribir a máquina, dejar que su uso solo ..
El elenco léxico es muy agradable.
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;
int main() {
string str = "0.6";
double dub = lexical_cast<double>(str);
cout << dub << endl;
}
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )para capturar la excepción.
Puede usar std :: stringstream:
#include <sstream>
#include <string>
template<typename T>
T StringToNumber(const std::string& numberAsString)
{
T valor;
std::stringstream stream(numberAsString);
stream >> valor;
if (stream.fail()) {
std::runtime_error e(numberAsString);
throw e;
}
return valor;
}
Uso:
double number= StringToNumber<double>("0.6");
Puede utilizar el elenco léxico de impulso:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
Nota: boost :: lexical_cast lanza una excepción, por lo que debe estar preparado para lidiar con eso cuando pase un valor no válido, intente pasar la cadena ("xxx")
Si no desea arrastrar todo el impulso, vaya con strtod(3)desde <cstdlib>: ya devuelve un doble.
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main() {
std::string num = "0.6";
double temp = ::strtod(num.c_str(), 0);
cout << num << " " << temp << endl;
return 0;
}
Salidas:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
¿Por qué atof () no funciona ... en qué plataforma / compilador estás?
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
Esta respuesta está respaldando litb en sus comentarios. Tengo profundas sospechas de que simplemente no está mostrando el resultado correctamente.
Una vez me pasó exactamente lo mismo. Pasé un día entero tratando de averiguar por qué obtenía un valor incorrecto en un int de 64 bits, solo para descubrir que printf ignoraba el segundo byte. No puede simplemente pasar un valor de 64 bits a printf como si fuera un int.
En cuanto a por qué atof()no funciona en la pregunta original: el hecho de que esté emitido al doble me hace sospechar. El código no debería compilarse sin #include <stdlib.h>, pero si la conversión se agregó para resolver una advertencia de compilación, entonces atof()no se declara correctamente. Si el compilador asume atof()devuelve un int, fundición que va a resolver el aviso de conversión, pero será no causa el valor devuelto a ser reconocido como un doble.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
debería funcionar sin advertencias.
En lugar de arrastrar Boost a la ecuación, puede mantener su cadena (temporalmente) como char[]y usar sprintf().
Pero, por supuesto, si está usando Boost de todos modos, realmente no es un gran problema.
De todos modos, no desea Boost lexical_cast para string <-> punto flotante. Ese subconjunto de casos de uso es el único conjunto en el que el impulso consistentemente es peor que las funciones anteriores, y básicamente concentraron todas sus fallas allí, porque sus propios resultados de rendimiento muestran un rendimiento 20-25X MÁS LENTO que usar sscanf e printf para tales conversiones.
Búscalo tú mismo. boost :: lexical_cast puede manejar algo así como 50 conversiones y si excluye las que involucran números de punto flotante, es tan buena o mejor como las alternativas obvias (con la ventaja adicional de tener una única API para todas esas operaciones). Pero trae flotadores y es como si el Titanic golpeara un iceberg en términos de rendimiento.
Las antiguas funciones str-> double dedicadas pueden realizar 10000 análisis en algo así como 30 ms (o mejor). lexical_cast tarda unos 650 ms en hacer el mismo trabajo.
Mi problema:
Mi solución (usa la función de Windows _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";
// Use this for error detection
wchar_t* stopString;
// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C"));
if (wcslen(stopString) != 0)
{
// ... error handling ... we'll run into this because of the separator
}
HTH ... me tomó bastante tiempo llegar a esta solución. Y todavía tengo la sensación de que no sé lo suficiente sobre localización de cadenas y esas cosas ...