Converteer float naar std::string in C++

Ik heb een float-waarde die in een std::string moet worden geplaatst. Hoe converteer ik van float naar string?

float val = 2.5;
std::string my_val = val; // error here

Antwoord 1, autoriteit 100%

Tenzij je je zorgen maakt over de prestaties, gebruik dan stringstreams :

#include <sstream>
//..
std::ostringstream ss;
ss << myFloat;
std::string s(ss.str());

Als je het goed vindt met Boost, lexical_cast<&gt ; is een handig alternatief:

std::string s = boost::lexical_cast<std::string>(myFloat);

Efficiënte alternatieven zijn b.v. FastFormat of gewoon de C-stijl functies.


Antwoord 2, autoriteit 96%

Vanaf C++11 biedt de standaard C++-bibliotheek de functie std::to_string(arg) met verschillende ondersteunde typen voor arg.


Antwoord 3, autoriteit 40%

Belangrijk:
Lees de notitie aan het einde.

Snel antwoord:
Gebruik to_string(). (beschikbaar sinds c++11)
voorbeeld:

#include <iostream>   
#include <string>  
using namespace std;
int main ()
{
    string pi = "pi is " + to_string(3.1415926);
    cout<< "pi = "<< pi << endl;
  return 0;
}

voer het zelf uit: http://ideone.com/7ejfaU
Deze zijn ook beschikbaar:

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);

Belangrijke opmerking:
Zoals @Michael Konecny ​​terecht opmerkte, is het gebruik van to_string() op zijn best riskant, aangezien het zeer waarschijnlijk onverwachte resultaten zal opleveren.
Van http://en.cppreference.com/w/cpp/string/basic_string/ to_string :

Bij typen met drijvende komma kan std::to_string onverwachte resultaten opleveren aangezien het aantal significante cijfers in de geretourneerde tekenreeks nul kan zijn, zie het voorbeeld.
De retourwaarde kan aanzienlijk verschillen van wat std::cout standaard afdrukt, zie het voorbeeld.
std::to_string vertrouwt op de huidige landinstelling voor opmaakdoeleinden, en daarom gelijktijdige aanroepen naar std::to_string van
meerdere threads kunnen leiden tot gedeeltelijke serialisatie van oproepen. C++17
biedt std::to_chars als een beter presterende locale-onafhankelijke
alternatief.

De beste manier zou zijn om stringstream te gebruiken, zoals anderen zoals @dcp demonstreerden in zijn antwoord.:

Dit probleem wordt gedemonstreerd in het volgende voorbeeld:
voer het voorbeeld zelf uit: https://www.jdoodle.com/embed/v0/T4k

#include <iostream>
#include <sstream>
#include <string>
template < typename Type > std::string to_str (const Type & t)
{
  std::ostringstream os;
  os << t;
  return os.str ();
}
int main ()
{
  // more info : https://en.cppreference.com/w/cpp/string/basic_string/to_string
  double    f = 23.43;
  double    f2 = 1e-9;
  double    f3 = 1e40;
  double    f4 = 1e-40;
  double    f5 = 123456789;
  std::string f_str = std::to_string (f);
  std::string f_str2 = std::to_string (f2); // Note: returns "0.000000"
  std::string f_str3 = std::to_string (f3); // Note: Does not return "1e+40".
  std::string f_str4 = std::to_string (f4); // Note: returns "0.000000"
  std::string f_str5 = std::to_string (f5);
  std::cout << "std::cout: " << f << '\n'
    << "to_string: " << f_str << '\n'
    << "ostringstream: " << to_str (f) << "\n\n"
    << "std::cout: " << f2 << '\n'
    << "to_string: " << f_str2 << '\n'
    << "ostringstream: " << to_str (f2) << "\n\n"
    << "std::cout: " << f3 << '\n'
    << "to_string: " << f_str3 << '\n'
    << "ostringstream: " << to_str (f3) << "\n\n"
    << "std::cout: " << f4 << '\n'
    << "to_string: " << f_str4 << '\n'
    << "ostringstream: " << to_str (f4) << "\n\n"
    << "std::cout: " << f5 << '\n'
    << "to_string: " << f_str5 << '\n'
    << "ostringstream: " << to_str (f5) << '\n';
  return 0;
}

uitvoer:

std::cout: 23.43
to_string: 23.430000
ostringstream: 23.43
std::cout: 1e-09
to_string: 0.000000
ostringstream: 1e-09
std::cout: 1e+40
to_string: 10000000000000000303786028427003666890752.000000
ostringstream: 1e+40
std::cout: 1e-40
to_string: 0.000000
ostringstream: 1e-40
std::cout: 1.23457e+08
to_string: 123456789.000000
ostringstream: 1.23457e+08 

Antwoord 4, autoriteit 28%

Je kunt een sjabloon definiëren die niet alleen werkt met doubles, maar ook met andere typen.

template <typename T> string tostr(const T& t) { 
   ostringstream os; 
   os<<t; 
   return os.str(); 
} 

Dan kun je het voor andere typen gebruiken.

double x = 14.4;
int y = 21;
string sx = tostr(x);
string sy = tostr(y);

Antwoord 5, autoriteit 8%

Gebruik std::to_chars eenmaal uw standaardbibliotheek biedt het:

std::array<char, 32> buf;
auto result = std::to_chars(buf.data(), buf.data() + buf.size(), val);
if (result.ec == std::errc()) {
  auto str = std::string(buf.data(), result.ptr - buf.data());
  // use the string
} else {
  // handle the error
}

De voordelen van deze methode zijn:

  • Het is locale-onafhankelijk en voorkomt bugs bij het schrijven van gegevens naar formaten zoals JSON waarvoor ‘.’ als een decimale punt
  • Het biedt de kortste decimale weergave met retourgaranties
  • Het is potentieel efficiënter dan andere standaardmethoden omdat het geen landinstelling gebruikt en geen toewijzing vereist

Helaas is std::to_string van beperkt nut met drijvende komma omdat het de vaste representatie gebruikt, kleine waarden naar nul afrondt en lange strings produceert voor grote waarden, bijvoorbeeld

auto s1 = std::to_string(1e+40);
// s1 == 10000000000000000303786028427003666890752.000000
auto s2 = std::to_string(1e-40);
// s2 == 0.000000

C++20 krijgt mogelijk een handiger std::format API met dezelfde voordelen als std::to_chars als de P0645 normvoorstel wordt goedgekeurd.


Antwoord 6, autoriteit 7%

Je kunt std::to_string in C++11

float val = 2.5;
std::string my_val = std::to_string(val);

Antwoord 7, autoriteit 2%

Als je je zorgen maakt over de prestaties, bekijk dan de Boost::lexical_cast bibliotheek.


Antwoord 8

Deze tutorial geeft een eenvoudige, maar elegante oplossing, die ik transcribeer:

#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
  BadConversion(std::string const& s)
    : std::runtime_error(s)
    { }
};
inline std::string stringify(double x)
{
  std::ostringstream o;
  if (!(o << x))
    throw BadConversion("stringify(double)");
  return o.str();
}
...
std::string my_val = stringify(val);

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes