Estou tentando converter std::stringpara float/double. Eu tentei:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Mas sempre retorna zero. Quaisquer outras maneiras?
Estou tentando converter std::stringpara float/double. Eu tentei:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Mas sempre retorna zero. Quaisquer outras maneiras?
Respostas:
std::string num = "0.6";
double temp = ::atof(num.c_str());
Para mim, é uma sintaxe C ++ válida para converter uma string em um double.
Você pode fazer isso com stringstream ou boost :: lexical_cast, mas eles vêm com uma penalidade de desempenho.
Ahaha você tem um projeto Qt ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Observação extra:
se os dados de entrada forem a const char*, QByteArray::toDoubleserá mais rápido.
A Biblioteca Padrão (C ++ 11) oferece a funcionalidade desejada com std::stod:
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
Geralmente, para a maioria dos outros tipos básicos, consulte <string>. Existem alguns novos recursos para strings C também. Vejo<stdlib.h>
ostringstreamem si era simplesmente muito longo para digitar, quanto mais usar ..
O elenco lexical é muito bom.
#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 a exceção.
Você pode 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");
Você pode usar o reforço de elenco 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 lança exceção, então você deve estar preparado para lidar com isso quando passar um valor inválido, tente passar string ("xxx")
Se você não quiser arrastar todo o impulso, vá com strtod(3)de <cstdlib>- ele já retorna um duplo.
#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;
}
Saídas:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
Por que atof () não funciona ... em qual plataforma / compilador você está?
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
Esta resposta está apoiada em pouco nos seus comentários. Tenho profundas suspeitas de que você simplesmente não está exibindo o resultado corretamente.
A mesma coisa aconteceu comigo uma vez. Passei um dia inteiro tentando descobrir por que estava obtendo um valor ruim em um int de 64 bits, apenas para descobrir que printf estava ignorando o segundo byte. Você não pode simplesmente passar um valor de 64 bits para printf como se fosse um int.
Quanto a por que atof()não está funcionando na pergunta original: o fato de que é lançado para dobrar me deixa desconfiado. O código não deve ser compilado sem #include <stdlib.h>, mas se o elenco foi adicionado para resolver um aviso de compilação, então atof()não foi declarado corretamente. Se o compilador assume atof()retorna um int, lançando ele vai resolver o aviso de conversão, mas vai não causa o valor de retorno para ser reconhecido como um duplo.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
deve funcionar sem avisos.
Em vez de arrastar Boost para a equação, você pode manter sua corda (temporariamente) como um char[]e usar sprintf().
Mas é claro que se você estiver usando Boost de qualquer maneira, não é um grande problema.
Você não quer Boost lexical_cast para string <-> ponto flutuante de qualquer maneira. Esse subconjunto de casos de uso é o único em que o boost consistentemente é pior do que as funções mais antigas - e eles basicamente concentraram todas as suas falhas ali, porque seus próprios resultados de desempenho mostram um desempenho 20-25X MAIS LENTO do que usar sscanf e printf para tais conversões.
Pesquise no Google. boost :: lexical_cast pode lidar com algo como 50 conversões e se você excluir aquelas envolvendo ponto flutuante # é tão bom ou melhor quanto as alternativas óbvias (com a vantagem adicional de ter uma única API para todas essas operações). Mas traga carros alegóricos e é como o Titanic batendo em um iceberg em termos de desempenho.
As antigas funções str-> double dedicadas podem fazer 10.000 análises em cerca de 30 ms (ou melhor). lexical_cast leva algo como 650 ms para fazer o mesmo trabalho.
Meu problema:
Minha solução (usa a função do 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 ... demorei muito para chegar a essa solução. E ainda tenho a sensação de que não sei o suficiente sobre localização de cordas e outras coisas ...