c++ - primaria - std:: string para flotar o duplicar
fuerza de empuje (15)
El reparto léxico es muy bueno.
#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;
}
Estoy tratando de convertir std::string
en float/double
. Lo intenté:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Pero siempre regresa a cero. ¿Alguna otra manera?
En cuanto a por qué atof()
no está funcionando en la pregunta original: el hecho de que se duplique me hace sospechar. El código no debe compilarse sin #include <stdlib.h>
, pero si el molde se agregó para resolver una advertencia de compilación, entonces atof()
no se ha declarado correctamente. Si el compilador asume que atof()
devuelve un int, la conversión resolverá la advertencia de conversión, pero no hará que el valor de retorno se reconozca 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, puedes mantener tu cadena (temporalmente) como un char[]
y usar sprintf()
.
Pero, por supuesto, si estás usando Boost de todos modos, realmente no es un gran problema.
Esta respuesta está respaldando en sus comentarios. Tengo profundas sospechas de que simplemente no muestra el resultado correctamente.
Me pasó exactamente lo mismo una vez. Pasé todo un día tratando de descubrir por qué estaba obteniendo un mal valor en un int de 64 bits, solo para descubrir que printf estaba ignorando el segundo byte. No se puede simplemente pasar un valor de 64 bits a printf como si fuera un int.
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);
Supongo que la Biblioteca estándar también se convierte internamente, pero de esta forma hace que el código sea más limpio. Generalmente para la mayoría de los otros tipos básicos, vea <string>
. También hay algunas características nuevas para las cadenas C. Ver <stdlib.h>
La forma de C ++ 11 es usar std :: stod y std :: to_string. Ambos funcionan en Visual Studio 11.
Mi problema:
- Cadena local independiente a doble (separador decimal siempre ''.'')
- Error de detección si falla la conversión de cadena
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 llevó bastante tiempo llegar a esta solución. Y todavía tengo la sensación de que no sé lo suficiente sobre la localización de cadenas y esas cosas ...
No desea que Boost lexical_cast para cadena <-> coma flotante de todos modos. Ese subconjunto de casos de uso es el único conjunto cuyo impulso es siempre peor que las funciones anteriores, y básicamente concentraron todas sus fallas allí, porque sus propios resultados de desempeño muestran un rendimiento 20-25X MÁS LENTO que el uso de sscanf y printf para tales conversiones.
Google usted mismo. boost :: lexical_cast puede manejar algo así como 50 conversiones y si excluyes los que involucran puntos flotantes es tan bueno o mejor que las alternativas obvias (con la ventaja adicional de tener una única API para todas esas operaciones). Pero traiga flotadores y es como el Titanic golpeando un iceberg en términos de rendimiento.
Las antiguas y dedicadas funciones str-> double pueden hacer 10000 análisis en algo así como 30 ms (o mejor). lexical_cast toma algo así como 650 ms para hacer el mismo trabajo.
Puede usar el impulso del lanzamiento léxico:
#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 tratar con ella cuando pase el valor no válido, intente pasar la cadena ("xxx")
Puedes 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");
Sí, con un elenco léxico. Use un operador de cadena de caracteres y <<, o use Boost, ya lo han implementado.
Tu propia versión podría verse así:
template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
}
Si no quiere 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;
}
Productos:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
Por qué atof () no funciona ... ¿en qué plataforma / compilador estás?
Tuve el mismo problema en Linux
double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}
funciona.
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
std::string num = "0.6";
double temp = ::atof(num.c_str());
Lo hace por mí, es una sintaxis C ++ válida para convertir una cadena en un doble.
Puede hacerlo con stringstream o boost :: lexical_cast, pero estos vienen con una penalización de rendimiento.
Ahaha, tienes un proyecto de Qt ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Nota extra:
Si los datos de entrada son const char*
, QByteArray::toDouble
será más rápido.